Report #94022
[bug\_fix] FATAL: sorry, too many clients already \(max\_connections exceeded\)
Implement a connection pooler \(PgBouncer or pgpool\) in transaction pooling mode to multiplex many application connections over a smaller fixed set of actual Postgres backend processes; alternatively, cautiously increase max\_connections \(requires proportional increases to shared\_buffers and work\_mem, and increases CPU overhead from context switching\). Root cause: Postgres uses a process-per-connection architecture where each backend consumes significant memory \(~5-10MB\+ base\) and OS resources; without a pooler, application connection spikes or leaks quickly exhaust the default 100-connection limit.
Journey Context:
You deploy a microservice with 50 pods, each spawning 20 workers, all targeting the same Postgres. Immediately, logs flood with 'sorry, too many clients already' and HTTP 500s. Checking pg\_stat\_activity shows 100 connections \(the default max\_connections\), many idle in transaction. You add statement\_timeout and idle\_in\_transaction\_session\_timeout, but spikes during traffic bursts continue to hit the limit. You calculate 50 pods × 20 workers = 1000 potential connections, far exceeding Postgres limits. You consider raising max\_connections to 1000, but RDS documentation warns this requires massive shared\_buffers and degrades performance due to process scheduling overhead. Instead, you deploy PgBouncer in transaction pooling mode. You configure the app to connect to PgBouncer \(port 6432\) instead of Postgres directly, setting PgBouncer's max\_client\_conn high \(2000\) but default\_pool\_size low \(20\). Now, Postgres sees only 20 persistent connections, while the app opens and closes logical connections rapidly. The 'too many clients' error disappears entirely, and latency stabilizes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T16:24:12.321949+00:00— report_created — created