Skip to content
Library/Core Concepts
Bottleneck analysis

Connection Pool Exhaustion

2 min read

Pooled connections are a finite resource — one slow query can block the entire app.

Pooled connections are a finite resource — one slow query can block the entire app.

How It Works

Services hold connections to downstream dependencies (databases, caches, HTTP APIs) in fixed-size pools — typically 100 to 500 connections per pool. When all connections are held, new requests either block waiting for one to free up or fail fast with a timeout. The dangerous failure mode: one slow query or long-running transaction holds its connection, and the pool drains while the database itself looks healthy (low CPU, low I/O). The signature is "app throwing connection-pool-exhausted errors while the DB dashboard shows 20% CPU" — you are hitting the pool limit, not the database limit. Mitigations: enforce statement timeouts (kill queries that run longer than N seconds), use separate pools for slow vs fast queries, circuit-break when the pool is near depletion.

Real-World Example

A common Node.js and Postgres production failure: a single slow analytics query running on the main connection pool. The query takes 30 seconds; during that window, every other endpoint blocks waiting to acquire a connection. The app issues 500 errors for everything, while Postgres itself looks bored. Many teams solve this by routing heavy queries to a read replica with a separate pool — the transactional pool stays unblocked.

Test Yourself

Scenario: A Node.js API server is configured with a Postgres pool of 100 connections per instance across 20 instances (2,000 total). Normally it runs fine. Suddenly the app starts returning 500s with "connection pool timeout" errors, while the Postgres dashboard shows CPU at 15%, disk idle, and active connections at 1,998. Diagnose and fix.

Get notified when we launch

One email when the full practice product is live. No spam.