psycopg2 FATAL: sorry, too many clients already
Fixes Postgres FATAL: sorry, too many clients already via psycopg2. Use when new connections are refused, when connection count hits max_connections, or when an agent spawns connections without pooling. Not for auth failures, for slow queries, or for pool exhaustion inside one app.
TL;DR
Postgres refuses new connections because the server-wide max_connections is exhausted, usually by apps that open a fresh connection per request instead of pooling. Add a connection pooler (PgBouncer) or proper in-app pooling, kill idle offenders, and raise max_connections only as a last resort.
psycopg2 FATAL: sorry, too many clients alreadyUse this when
- New psycopg2 connections fail with this FATAL
- The error appears under load or as services scale
- An agent opens a new connection per query
Not for this skill when
- The password is rejected (thats auth)
- Queries are slow but connections succeed (thats performance)
- One app exhausts its own pool (thats the app pool, not the server)
Steps
- See who holds the connections:
SELECT application_name, state, count(*)
FROM pg_stat_activity GROUP BY 1, 2 ORDER BY 3 DESC;Expected output: the top offenders by count and state. Lots of idle connections from one app means no pooling on that side.
- Free the obviously dead ones (carefully):
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE state = 'idle' AND backend_type = 'client backend'
AND application_name = 'offending_app';Expected output: the count drops and new connections succeed. This is triage, not a fix; they will come back without pooling.
- Put PgBouncer (or your cloud's pooler) between the apps and Postgres:
app to pgbouncer (transaction pooling) to postgresExpected output: hundreds of app connections multiplex onto a handful of server connections. This is the real fix for "too many clients" at scale.
- In the app, use one pooled connection source instead of connect-per-query:
from psycopg2 import pool
pg_pool = pool.ThreadedConnectionPool(2, 20, dsn=DSN)Expected output: the app reuses connections. psycopg2 has no built-in pooling magic; you must add it.
Variant phrasings
too many clients after adding a new service
The new service doesnt pool. Every new service needs pooling from day one.
happens at the same time daily
A cron or batch job opens a connection per row. Batch the work inside one connection.
Why it happens
Postgres allocates real resources per connection, so max_connections (default 100) is a hard ceiling. Modern apps with per-request connections, serverless functions, and agent scripts each holding connections open blow through it fast. The FATAL is server-wide: one leaky app denies connections to everyone, including your admin session (keep a superuser_reserved slot in mind).
Edge cases
- Raising maxconnections without adding memory risks OOM; each connection costs workmem-sized buffers.
- Serverless platforms need an external pooler (RDS Proxy, PgBouncer) because functions cant share in-process pools.
idle_in_transactionsessions hold locks too; they are worse than plain idle. Find the code that starts transactions and never commits.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_8KyRoL7udo7GIdkAksCdWw
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.