Postgres Pool Exhausted¶
All connections in the asyncpg pool are in use. New requests wait for a connection and time out with AdapterTimeoutError.
Symptoms¶
- HTTP requests to database-backed routes time out (>
connection_timeoutseconds) AdapterTimeoutErrorin logs withoperation="get"oroperation="create"- OTel spans show long duration on
repository.*.getchild spans is_ready()may returnFalseif pool health check cannot acquire a connection
Diagnosis¶
1. Check pool size vs concurrent load.
Pool size is set via POOL_SIZE env var (default: 10 in PostgresSettings). If concurrent requests exceed pool size, waiters queue up.
2. Check for leaked connections.
A connection is leaked when an adapter method raises an exception inside a transaction without rolling back and releasing. Look for spans with status ERROR that correspond to long-held connections.
3. Check operation_timeout.
BaseAdapterSettings.operation_timeout defaults to 10 seconds. If queries regularly take longer than this, the timeout fires before the query completes — increase the timeout or optimise the query.
Recovery¶
Immediate: Increase pool size via env var and redeploy:
If connections are leaked: Restart the container to force-close all connections:
Prevention¶
Use async with pool.acquire() as conn: (context manager) in all adapter methods. The context manager releases the connection on exit even if an exception is raised, preventing leaks.