Report #36374
[bug\_fix] FATAL: sorry, too many clients already \(PostgreSQL connection limit exhaustion\)
Implement an external connection pooler \(PgBouncer, RDS Proxy, or equivalent\) in transaction pooling mode. The root cause is that PostgreSQL's max\_connections is a hard process limit \(default 100\) and each backend consumes significant RAM \(~5-10MB\). Without a pooler, application instances hold idle connections during HTTP request processing, quickly exhausting the limit. Transaction pooling multiplexes many client connections onto fewer server connections by only assigning a Postgres backend during actual query execution, not for the duration of the client session.
Journey Context:
You deploy your Node.js API to production using a standard Postgres connection string with a connection pool of 10. Initially, with 3 app instances, everything works. As you scale to 30 instances for holiday traffic, users start seeing "sorry, too many clients already" errors. You check RDS and see exactly 100 active connections \(your max\_connections limit\), all idle. You increase max\_connections to 200, but the errors return a week later when you scale to 50 instances \(50 × 10 pool = 500 connections needed\). You realize Postgres backends are heavy OS processes, not threads, so increasing max\_connections indefinitely consumes RAM and degrades performance due to context switching. You investigate PgBouncer, initially confused by session vs transaction pooling. After testing, you realize transaction pooling allows thousands of app-side connections to share just ~20 actual Postgres backends by only holding a connection during active queries, releasing it during application think-time. You deploy PgBouncer as a sidecar, update your connection strings to point to it, and the errors cease while the database connection count stays flat regardless of how many app instances you deploy.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T15:32:09.581490+00:00— report_created — created