Skip to content

Databases Under Load

Databases under load are database-backed systems where request rate, connection limits, and connection hold time determine capacity as much as query speed. The usual failure is not a slow SELECT but a saturated connection pool: requests wait to borrow a connection, latency rises, and the database may still look mostly healthy.

The problem is that database access is gated by a finite number of connections. Every web request, job, or function that checks out a connection occupies one slot until it gives it back. When arrivals exceed the rate at which slots are released, work queues in the pool. This can happen even when individual SQL statements are quick, because users experience the wait before the query as part of request latency.

Little's Law gives the concrete model: in-flight work equals throughput multiplied by time in the system. For a pool, the useful approximation is that needed connections equal request rate multiplied by connection hold time. Hold time is not just database execution; it includes any application code, transaction scope, object mapping, or remote call performed while the connection remains checked out.

The trade-off is that larger pools are not free capacity. More application connections can overload Postgres, MySQL, or a proxy before database CPU is the limiting resource. Bigger pools also hide bad checkout behaviour until a sharper failure. Smaller pools protect the database but create visible waiting sooner. The honest sizing answer depends on arrival rate, hold time, instance count, database limits, and acceptable queueing.

Engineers meet this in HikariCP, ActiveRecord, PgBouncer, RDS Proxy, Cloud SQL, Kubernetes pod settings, serverless database access, and metrics dashboards. The useful signals are active connections, pending borrowers, checkout duration, transaction duration, and pool wait time. A common misunderstanding is to look only at query latency; if pool wait dominates, optimising the SQL will not fix the bottleneck.

Common questions

Why can HTTP latency be high when database queries look fast?
Query timing often starts after a connection has been acquired. If the pool is saturated, a request may spend most of its time waiting in the application or proxy queue before the database sees anything. Database dashboards can therefore show fast SQL while users see slow responses.
Does increasing the pool size fix database load problems?
Sometimes, but it often moves the bottleneck. A larger pool reduces local waiting only if the database and any proxy can handle the extra concurrent connections. Across many pods or workers, multiplying pool size by instance count can exhaust server connection limits and make the incident worse.
What is connection hold time?
Connection hold time is the duration between checking a connection out of the pool and returning it. It includes SQL execution, but also time spent inside a transaction, application processing, ORM work, and any accidental external calls made while the connection is still held.
How should an engineer reason about pool capacity?
Use Little's Law as a first model: required concurrency is throughput times hold time. Then verify it with production metrics for active connections, pending requests, wait duration, and transaction duration. The model is approximate, but it points attention to the variable that usually matters: how long each request occupies a scarce connection.