What they're testing
Whether you think in terms of saturation. Pushing concurrency past the saturation point LOWERS throughput, and plenty of people don't believe it until they measure it.
The short answer~30 seconds
Usually lower. The database has a fixed number of cores and spindles; past that point, extra connections only add context switching, lock contention and buffer-cache pressure — throughput flattens then falls while p99 latency climbs. The familiar starting formula is roughly cores × 2 + spindles, which lands on a surprisingly small number, often 10–20 per node.
The long answer
The wrong intuition treats a connection as a place where work happens. It's really a place where work waits. If the database is at peak efficiency with 20 concurrent queries, letting 500 in doesn't make it faster — it moves the queue from somewhere you control (the application pool) into somewhere you don't (the OS scheduler), where each query holds locks and memory while it waits.
Postgres adds a second cost: each connection is a separate process, taking several megabytes plus a share of shared memory. A few hundred idle connections still consume RAM that should have been page cache. That's the reason PgBouncer's transaction pooling exists — it lets thousands of client-side connections map onto a few dozen server-side ones.
Before touching numbers though, ask why the pool is exhausted. Very often it's transactions held too long: an HTTP call sitting between BEGIN and COMMIT, or a background job sharing the pool with the request path. Fixing that usually drops connection demand by an order of magnitude, and no configuration substitutes for it.
At senior level the complete answer adds pool separation: the request path, background jobs and migrations should have their own pools with their own limits, so a runaway job can't consume the connections real users need. It's a bulkhead, and it turns a system-wide incident into a local one.
What they'll ask next
?What about serverless, where each instance has its own pool?
That's exactly where the traditional pool model breaks: 500 lambdas × a pool of 5 is 2,500 connections. You need a proxy in front (PgBouncer, RDS Proxy, the Supabase pooler) or an HTTP driver that holds no connection. Raising this shows you've kept up with how things are actually deployed now.
?Which metric tells you the pool is right-sized?
Connection ACQUIRE WAIT time, not the number of connections in use. Near-zero wait with the database not saturated means the pool is fine; rising wait while database CPU stays low means the bottleneck is elsewhere — usually locks or I/O.
These lose points
- Raising
max_connectionsto 2,000 and calling it fixed. You've moved the queue somewhere darker. - Never asking how long transactions are held. That's nearly always the real cause.
These score well
- Noting that a smaller pool improves p99 even at identical throughput, because a controlled queue has predictable wait times.