Databases
Connection pooling: multiple-choice review
Six questions that cut across the whole unit. Each mirrors a decision you make at 02:14 with a pager going off — not a definition to recite, but a tradeoff to weigh when the pool is empty and cl_waiting is climbing.
Confirm you can connect the Postgres process model, PgBouncer pooling modes, sizing math, the hold-time root cause of exhaustion, and pooler selection — the synthesis the seven lessons built toward.
A team runs 40 application workers, each with a client pool of max 20, against Postgres with max_connections = 100. They direct-connect (no PgBouncer) and see 'FATAL: sorry, too many clients already'. What is the real fix?
An app on PgBouncer session mode switches to transaction mode for the multiplexing win. A `SET search_path = 'app, public'` issued once at connect time silently stops taking effect. Why, and what is the correct fix?
A 16-core Postgres box (NVMe, working set in RAM) is behind PgBouncer. An engineer sets default_pool_size = 200 to 'match peak concurrency' and p99 gets worse. What is the throughput-optimal pool_size and why?
At 02:14 PgBouncer reports pool = 24, cl_waiting = 180, and the app returns 503s. pg_stat_activity shows 19 backends in state 'idle in transaction' with max xact age 8 minutes. The pool was sized correctly that morning. What is happening?
A team on PgBouncer 1.20 disabled driver prepared statements to avoid 'prepared statement does not exist' errors in transaction mode, losing ~20% throughput. They want both transaction-mode multiplexing AND prepared statements in 2026. What unlocks it?
A multi-tenant B2B SaaS runs 10,000 tenant databases, ~50 concurrent users each, with serverless functions that cold-start under load. PgBouncer on one node pegs a single CPU core and cold starts cause connection storms. Which architecture fits?
The through-line across the unit is one chain: Postgres forks a heavyweight process per connection, so backend count must stay near (cores × 2) — which a pooler delivers by multiplexing thousands of cheap client connections in transaction mode. Transaction mode costs you connect-time session state (SET, LISTEN, SQL PREPARE, session advisory locks), each with an exact safe substitute, and PgBouncer 1.21+ finally makes prepared statements compatible. When the pool empties, the cause is almost always hold-time — a slow query or an external call inside a transaction — not size; idle_in_transaction_session_timeout is the free safety net. Reach past PgBouncer only when you have measured its single-thread ceiling or face serverless/multi-tenant scale.