Scenario · Connections & Pooling
Pool size misconfiguration
A sandboxed PostgreSQL incident — investigate with your own tools, submit a fix, and get deterministic Detect / Fix / Trap scoring.
L3 · 10–15 min · runs locally in Docker
Launch
Start this scenario
Boot it in a real PostgreSQL sandbox and investigate with psql, EXPLAIN and pg_stat_statements.
ride postgres start stage-03/09-pool-size-misconfigurationPart of these paths
Show the postmortem & investigation hints spoilers
Pool size misconfiguration Type: incident simulation · Topic: Connections & Pooling · Level: L3 · Duration: 10–15 min Launch: ride postgres start stage-03/09-pool-size-misconfiguration POSTMORTEM (root cause · how it was found · the fix · lesson) Root cause: PgBouncer's default_pool_size was set far too small for the offered load. PostgreSQL had plenty of free connection slots and answered direct queries instantly, but the pooler only ever opened a couple of server connections, so clients queued behind them (cl_waiting > 0). The throughput ceiling was the pool's configuration, not the database. How it was found: pg_stat_activity was far from max_connections and direct queries were fast; PgBouncer's SHOW POOLS showed clients waiting on a tiny pool and SHOW CONFIG showed an undersized default_pool_size. The mitigation: the durable fix is to raise default_pool_size and reload PgBouncer; to clear the immediate queue, free the busy server connections so waiters are promoted (cl_waiting → 0). Lesson: distinguish a Postgres capacity problem from a pooler sizing problem — "Postgres has headroom but the app is throttled" points at default_pool_size. Size the pool to the workload; don't raise Postgres max_connections (wrong layer) or add indexes. INVESTIGATION HINTS (the staged path to diagnose and fix) 1. The app is throttled but PostgreSQL is nowhere near max_connections and direct queries are fast. The bottleneck is PgBouncer's pool size, not the database. On the admin console: SHOW POOLS (cl_waiting > 0, every server slot busy) and SHOW CONFIG (default_pool_size is tiny). 2. Confirm Postgres has capacity: SELECT count(*) FROM pg_stat_activity; SHOW max_connections; — plenty of headroom. The pool is artificially small for the offered load. 3. The durable fix is to raise default_pool_size in PgBouncer and reload. To relieve the incident now, free the busy server connections (terminate the pool_client backends) so the queue drains; cl_waiting drops to 0. Do NOT raise Postgres max_connections — that is the wrong layer.