Report #9666
[bug\_fix] FATAL: sorry, too many clients already \(Postgres connection limit exhaustion\)
Implement a connection pooler \(PgBouncer or Supavisor\) in transaction pooling mode to multiplex many application connections over a small fixed set of actual Postgres backend processes; alternatively increase max\_connections only as a temporary band-aid.
Journey Context:
Developer deploys a Python service with 20 replicas to production, each maintaining a SQLAlchemy pool of 10 connections. Under load, the app intermittently crashes with "FATAL: sorry, too many clients already." Investigation reveals Postgres max\_connections is set to 100, and 20 replicas × 10 connections = 200 attempts. Developer tries raising max\_connections to 300, but the OOM killer begins terminating Postgres backends because each connection forks a new process consuming ~10MB RAM. After reading Postgres architecture docs, developer realizes connections are heavyweight OS processes, not threads. The solution is inserting PgBouncer in transaction pooling mode \(pool\_mode=transaction\) between app and Postgres. This allows 1000 application-side connections to share just 20 actual Postgres connections, because PgBouncer releases the backend to the pool after each transaction commit, reassigning it to the next waiting client. This works because Postgres protocols allow multiplexing at the transaction boundary, not session boundary.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T08:46:19.383580+00:00— report_created — created