Lesson 11 of 12

Connection Overhead: Why Pooling Is Mandatory at Scale

Applies to PostgreSQL 13–17 Last reviewed May 2026 Grounded in source

The one thing to understand first

PostgreSQL uses a process-per-connection model: the postmaster fork()s a dedicated backend for every client connection (src/backend/postmaster/postmaster.c). That backend lives until the client disconnects. This design is robust and simple, but it makes connections relatively expensive — unlike thread-per-connection databases, each PostgreSQL connection carries OS-process weight.

The right number of active connections is small — a few times your core count — but applications want to hold far more than they use at any instant. A pooler exists to bridge exactly that mismatch. “Just raise max_connections” makes the problem worse, not better.

The real costs of a connection

  • Memory. Each backend has private memory for caches (catalog, plan), plus its share of work for sorts/hashes. Thousands of mostly-idle backends consume gigabytes doing nothing.
  • Snapshot cost. Taking an MVCC snapshot scans the ProcArray of all backends (see the snapshots article). More backends → more expensive GetSnapshotData() → contention on every transaction, even idle ones add to the array.
  • Context switching. The OS scheduler juggling thousands of processes wastes CPU on switches rather than work.
  • Connection setup. Fork, authentication, and backend initialisation cost milliseconds — punishing for short-lived connections that reconnect constantly.

Why “just raise max_connections” fails

Setting max_connections = 5000 does not scale linearly — it amplifies all the costs above. Throughput typically peaks at a connection count near a small multiple of CPU cores and then declines as contention dominates. The correct number of active connections is small; the problem is that applications want to hold many connections while using few at any instant. That mismatch is exactly what a pooler resolves.

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • PgBouncer and pooling modes
  • Transaction mode caveats
  • A sane topology
  • Layer 3 — Watch it happen on your own database
  • Layer 4 — The levers this hands you
  • Layer 5 — What an Oracle DBA should expect vs what they get
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Was this helpful?

← Back to 02 — Performance: Query & Index Mastery