Lesson 21 · PostgreSQL in Go

pgx & the connection pool

How your Go services actually connect to Postgres.

Your win: explain what pgx is, why a connection pool matters, and how ours is configured — the foundation for the RLS trace that finishes this course.

pgx: the driver our repo uses

pgx (jackc/pgx) is a Go PostgreSQL driver and toolkit. It speaks the Postgres wire protocol directly — not through database/sql — and pairs with pgtype for rich types (Lesson 2). ⚠️ Our repo is mostly v4 (v4.18) with a few v5 files; don't mix their Tx/Row types across a boundary.1

Why a connection pool

Opening a connection (TCP + TLS + auth + session setup) for every query is slow. A connection pool (pgxpool) keeps a set of live connections and lends one out per query, returning it after. That bounds load on Postgres and makes "get a connection" nearly free.2

internal/golibs/database/pool_gcp.go:33
// NewPool: parse config → connect, with retry
poolconfig, _ := pgxpool.ParseConfig(connStr)
poolconfig.MaxConns        = cfg.MaxConns          // cap on concurrent connections
poolconfig.MaxConnIdleTime = cfg.MaxConnIdleTime
poolconfig.BeforeAcquire   = setPostgres[...]      // ← the tenant hook (Lesson 24)
pool, _ := pgxpool.ConnectConfig(ctx, poolconfig)
The knobs that matter MaxConns caps concurrency — too low starves the app, too high overwhelms Postgres (each connection is a backend process). MaxConnIdleTime reaps idle connections. These come from a per-DB PostgresDatabaseConfig (each service's database gets its own pool).
Anchor — and a preview Non-local environments dial through the Cloud SQL Go Connector (IAM auth) instead of raw TCP. The crucial line is BeforeAcquire = setPostgres: a hook that runs on every connection checkout to stamp the tenant onto the session — which is how RLS multi-tenancy works (Lesson 24). The pool isn't just performance; it's where per-request security gets injected.
Read this next

pgx + pgxpool

The driver README/wiki and the pool package docs (ParseConfig, ConnectConfig, pool sizing, hooks).

github.com/jackc/pgx
pkg.go.dev — pgx/v4/pgxpool

Check yourself (from memory)

Q1. A connection pool exists to…

Reuse avoids the cost of connecting per query and bounds load. MaxConns caps concurrency.

Q2. Our services use which Go driver?

pgx v4 (some v5), speaking the wire protocol directly with pgtype. Not database/sql.

Q3. pgxpool's MaxConns setting…

It bounds concurrent connections — each is a Postgres backend process, so it's a real resource.
What is pgx, why a connection pool, and how is ours configured?
recall, then click to reveal
pgx (jackc/pgx, v4 here with some v5) is a Go PostgreSQL driver + toolkit speaking the wire protocol directly (with pgtype), not via database/sql. A connection POOL (pgxpool) keeps live connections and lends one per query — connecting each time is expensive; the pool bounds DB load and makes acquire fast. Ours: database.NewPoolpgxpool.ParseConfig + ConnectConfig, with MaxConns and MaxConnIdleTime from a per-DB config; non-local uses the Cloud SQL Go Connector; a BeforeAcquire hook stamps the tenant on each checkout (Lesson 24).
Want to reason about pool sizing (why "connections ≠ threads", and pgbouncer)? Ask me.

1. jackc/pgx.

2. pgx/v4/pgxpool.