Connections are not free
Each Postgres backend connection forks a process and consumes ~10MB of RAM. Production Postgres typically caps connections at 100-200 — going higher hurts more than it helps. Modern web stacks (serverless functions, Lambda, Vercel) can spawn thousands of concurrent processes, each wanting its own connection. Math doesn't work.
The connection pooler
A connection pooler sits between your application and Postgres. Application processes connect to the pooler (cheap); the pooler maintains a small pool of real Postgres connections and multiplexes traffic. pgBouncer is the canonical tool. Most managed providers ship a pooler.
Pool modes
- Session pooling: connection is held for an entire client session. Limited multiplexing; safest semantics.
- Transaction pooling: connection is held only for the duration of a transaction. Far better multiplexing; loses session-level features (SET, prepared statements, LISTEN). The default for serverless.
- Statement pooling: connection released after each statement. Most aggressive; loses transactions. Rarely used.