CONCEPT Cited by 1 source
Connection pool exhaustion¶
Definition¶
A connection pool is a fixed-size set of pre-established database connections shared across application workers. An application worker takes a connection from the pool for the duration of a query (or transaction), then returns it.
Connection pool exhaustion is the state where every connection in the pool is in use; new requesters either:
- Wait for a connection to be returned (bounded-queue behaviour).
- Get rejected immediately (fail-fast behaviour).
- Create a new connection outside the pool (uncommon; defeats the pool's purpose).
Why it's a high-quality throttling signal¶
Among the metrics Shlomi Noach walks through in Part 1 of Anatomy of a Throttler (sources/2026-04-21-planetscale-anatomy-of-a-throttler-part-1), pool exhaustion is the one signal with a natural threshold:
"Who decides the size of the pool in the first place? If someone picked a number such as 50 or 100, isn't that number just artificial? It may well be, but pool size was likely chosen for some good reason(s). It is perhaps derived from some database configuration, which is itself derived from some hardware limitation. And while the choice of metric could possibly change arbitrarily, it is still sensible, as far as throttling goes, to push back when the pool is exhausted. The throttler thereby relies on the greater system configuration and does not introduce any new artificial thresholds."
In other words: the operator already chose a pool size based on:
max_connectionsin the database- Memory per backend (InnoDB / PostgreSQL backend overhead)
- Expected concurrency profile
- Connection-establishment cost / TLS handshake cost
A throttler that pushes back when the pool is 100% used inherits the existing system configuration as its threshold. It does not need to ask the operator to pick a new number.
Contrast with intermediate levels of utilisation¶
Pool exhaustion (100%) is a strong signal. Pool utilisation (60% vs 80%) is a much weaker one:
"An exhausted pool is a strong indication of excessive load, while the difference between a 60% and an 80% used pool is not as clear an indication."
This is why pool exhaustion is typically a binary throttling signal — "reject when full" — rather than a continuous one. Continuous levels conflate transient burstiness with sustained load in ways that are hard to separate without knowing workload shape.
Limits of the signal¶
- Pool connections span transactions, not queries. A connection can be held across multiple queries in a transaction, across multiple transactions, and across application logic between them. Pool exhaustion therefore reports on held connections, not on actively executing ones — a subtle distinction from concepts/threads-running-mysql.
- Per-pool, not per-database. Modern applications may have many pools (per-service, per-region, per-tenant); pool exhaustion in one does not necessarily indicate database-level distress.
- Pooler-level pools (PgBouncer, ProxySQL, VTGate) introduce a second tier of exhaustion — the database can be unexhausted while the pooler is full, and vice versa.
Relationship to queueing theory¶
Pool exhaustion is the queue-full state of a bounded queue: the
pool has capacity N, arrivals exceed the service rate so all N
slots are occupied, and new arrivals are rejected or stall. See
concepts/queueing-theory and concepts/backpressure for the
broader framing.
Seen in¶
- sources/2026-04-21-planetscale-anatomy-of-a-throttler-part-1
— canonical framing of pool exhaustion as the one
throttling-signal metric with a natural, system-configuration-
derived threshold. Noach lands on it as the positive counter-
example to
threads_runningand load average, both of which lack a stable threshold.
Related¶
- concepts/database-throttler — the use case where its natural-threshold property matters.
- concepts/backpressure — pool exhaustion is a canonical backpressure mechanism at the connection-acquisition layer.
- concepts/queue-length-vs-wait-time — pool length is length; acquire-wait-time is the corresponding wait-time signal.
- concepts/symptom-vs-cause-metric — exhaustion is still a symptom (the cause could be slow queries, lock contention, or genuine load) but the threshold is not arbitrary.
- systems/pgbouncer — canonical connection pooler for Postgres.