High severitycapacity
PostgreSQL Error:
53300
What does this error mean?
PostgreSQL returns SQLSTATE 53300 (`too_many_connections`) when a new connection request arrives but the server has already reached `max_connections`. The server immediately rejects the handshake — no queueing, no retry. In data-pipeline contexts this typically surfaces when multiple orchestrators (Airflow, ADF, dbt Cloud) and application backends all open connection pools against the same PostgreSQL instance. The error cascades quickly: one failed connection causes a task failure, which triggers retries that open even more connections, making the situation worse. Engineers typically see this as `FATAL: sorry, too many clients already` in PostgreSQL logs or as a connection-timeout error in the orchestrator's task log.
Common causes
- 1Multiple orchestrators (Airflow, ADF, dbt Cloud) and application servers each maintaining their own connection pools, collectively exceeding `max_connections`.
- 2`max_connections` left at the default value of 100, which is insufficient once more than a few concurrent pipelines run.
- 3Connection leak in application code — connections opened in a try block but not closed in a finally block, or ORM sessions not properly disposed after exceptions.
- 4No connection pooler (PgBouncer, Pgpool-II, RDS Proxy) between clients and PostgreSQL, so every client holds a direct backend process.
- 5Burst of retries after an initial failure — orchestrator retry policies open new connections before the failed ones are released, amplifying the problem.
- 6Long-running queries or transactions holding connections for minutes, blocking the pool from recycling them for other tasks.
- 7Managed service connection limits (Azure Database for PostgreSQL Basic tier caps at 50; RDS `db.t3.micro` at 112) lower than expected.
How to fix it
- 1Step 1: Check connection usage per state and application: `SELECT usename, application_name, state, count(*) FROM pg_stat_activity GROUP BY 1, 2, 3 ORDER BY 4 DESC;` — this shows which pool or app is consuming connections.
- 2Step 2: Identify and terminate idle connections sitting for more than 10 minutes: `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND state_change < now() - interval '10 min';`
- 3Step 3: Deploy PgBouncer in transaction-pooling mode between your clients and PostgreSQL. Set `default_pool_size` to 20 and `max_client_conn` to 200 as a starting point. For AWS: use RDS Proxy; for Azure: enable the built-in PgBouncer in Flexible Server.
- 4Step 4: Increase `max_connections` in `postgresql.conf` or via your managed service's parameter group. Also raise `shared_buffers` proportionally (~128kB per connection). Requires a server restart.
- 5Step 5: Set `idle_in_transaction_session_timeout = '5min'` in `postgresql.conf` to automatically kill connections stuck in idle-in-transaction state.
- 6Step 6: Audit each application's pool settings — in SQLAlchemy set `pool_size=5, max_overflow=10, pool_recycle=1800`; in Airflow set `sql_alchemy_pool_size=5` in airflow.cfg. Reduce pool sizes to fit within `max_connections` divided by the number of clients.
- 7Step 7: Reserve superuser connections by verifying `superuser_reserved_connections = 3` (default) so you can always connect as superuser to diagnose a full server: `psql -U postgres -h localhost`
Example log output
2026-05-11T06:00:02.417Z [FATAL] PostgreSQL: FATAL: sorry, too many clients already
2026-05-11T06:00:02.418Z [ERROR] Connection to database "analytics" failed: server rejected connection; max_connections (100) reached
2026-05-11T06:00:02.420Z [ERROR] Task 'load_orders_daily' failed: sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL: sorry, too many clients already (SQLSTATE 53300)