← Concepts

阅读中文版本

Connection Pool Saturation

Connection pool saturation happens when all pooled connections are held longer than requests arrive, queuing callers behind slow queries instead of shedding load cleanly.

database

Definition

Pool saturation is the state where every connection in a pool is busy and incoming work waits in a queue. It is usually caused by slow queries, transaction scope that includes remote calls, or undersized pools relative to actual database capacity. Symptoms are rising queue wait time, not rising query time.

Context and scope

Diagnosed via pool metrics (active, idle, waiting), thread dumps showing acquisition waits, and latency histograms where the tail is queueing rather than execution. Common during incidents where a slow downstream amplifies into a full outage.

Common misconceptions

  • A saturated pool means the database is overloaded — the database may be idle; the pool is starved by long holders
  • Bigger pools fix saturation — they mask it until the database limit itself becomes the bottleneck
  • Queueing is graceful degradation — unbounded queues turn a slowdown into timeouts plus pileups at every layer

Anti-patterns

  • Holding a transaction open across an HTTP call to a third party, pinning connections for seconds
  • Setting pool maximum to the database max_connections and treating the pool as the bottleneck rather than the guard
  • Retry storms against a saturated pool, where each waiting caller times out and retries, multiplying queue pressure

Related concepts

Related examples

Authoritative source

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

What it is

A pool converts connection setup cost into reusable capacity. Saturation is when that capacity is fully held: new requests block on acquisition. The user-visible latency is queue wait plus execution, and queue wait dominates long before anyone notices slow queries.

How it works

Pool metrics separate active, idle, and waiting threads. Saturating with low database CPU means holders are slow or stuck; saturating with high database CPU means the database is the real constraint. Little-style reasoning bounds useful pool size by cores and wait ratio — oversized pools add contention without throughput.

When to intervene

Bound the queue, set acquisition timeouts that fail fast, and enforce timeouts on queries themselves. Fix transaction scope so connections are held only for database work. Load-shed before the pool rather than after it.

Pitfalls

Retries aimed at a saturated pool amplify pressure exponentially. Health checks that grab a connection make saturation kill your liveness probes, cascading restarts. Measure acquisition time as its own metric; averages hide the bimodal split between instant and queued.