A connection pool is a fixed slot count plus a queue.
Opening a Postgres connection costs a TCP handshake, TLS, authentication and a forked backend process — single-digit to tens of milliseconds. A pool amortises that by keeping N open and handing them out: check out, use, check in.
So the latency a client observes is queue wait + query time. When the pool is saturated the first term dominates and the second is unchanged. That is why pg_stat_statements shows a fast query at the same moment the client sees a slow request: the two numbers measure different intervals, and they are both correct.
Exhaustion surfaces as a checkout timeout — PoolTimedOut, TimeoutError: QueuePool limit ... overflow. That is a capacity signal about your service, not a database fault.
The simulation makes it concrete: at capacity 1, the worst request waits 198 ms for a pool whose longest query is 25 ms.
