Report #100535
[bug\_fix] PostgreSQL: FATAL: sorry, too many clients already
Size each app's connection pool so that \(instances × pool\_max\) \+ PgBouncer/internal overhead \+ superuser\_reserved\_connections stays under PostgreSQL's max\_connections. Prefer an external pooler such as PgBouncer in transaction mode, close idle connections aggressively, and monitor pg\_stat\_activity.
Journey Context:
A FastAPI service is deployed with three replicas and a SQLAlchemy pool\_max\_size of 20, pointing at a managed Postgres with max\_connections=100. At normal load it works. During a traffic spike the logs start showing 'FATAL: sorry, too many clients already' and requests fail before any query runs. Checking pg\_stat\_activity shows many idle connections from the app holding state. The first guess is to raise max\_connections, but the DBA notes that every Postgres backend is a process and raising it too far hurts memory and the planner. The real issue is that pool\_max\_size is per instance, so 3 × 20 = 60 app connections, plus monitoring/backup/admin connections, can exceed 100. The fix is to treat max\_connections as a global budget: reserve superuser\_reserved\_connections \(default 3\), subtract monitoring and other apps, then divide the remainder by replica count to get the per-instance pool max. Where there are many short-lived requests, adding PgBouncer in transaction mode multiplexes many application sessions over far fewer Postgres backends, which is the standard remedy for connection-count contention.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-02T04:40:13.214426+00:00— report_created — created