PostgreSQL Error Guide: 'too many connections for role' Per-Role Connection Limits
Fix PostgreSQL 'too many connections for role': diagnose CONNECTION LIMIT settings, leaked connections, and pooling to stay under per-role caps.
- #postgres
- #troubleshooting
- #errors
- #connections
Exact Error Message
FATAL: too many connections for role "app_user"
The SQLSTATE is 53300 (too_many_connections), the same class as the cluster-wide limit error.
What the Error Means
PostgreSQL lets you cap the number of concurrent connections a specific role may hold using ALTER ROLE ... CONNECTION LIMIT n. When a role already has n active sessions and tries to open another, the new connection attempt fails immediately with too many connections for role. This is distinct from the cluster-wide remaining connection slots are reserved / too many clients already errors — here the global pool may have plenty of free slots, but this particular role has hit its own per-role ceiling.
This per-role limit is a useful guardrail in multi-tenant clusters: it stops one application or one misbehaving service from consuming all available connections at the expense of others. When you see it, the role has reached its configured rolconnlimit. The fix is either to raise that limit (if it is genuinely too low) or, more often, to stop the role from leaking or over-allocating connections.
Common Causes
- A CONNECTION LIMIT that is lower than the application’s pool size. If the role is capped at 20 but the app’s connection pool can open 50, the excess connections fail.
- Connection leaks. Application code that opens connections without returning them to the pool (or without closing) steadily consumes the role’s slots until the limit is hit.
- Multiple application instances sharing one role. Several pods/replicas each running a 20-connection pool against a role limited to 30 will collectively exceed it.
- Idle connections not being recycled. Long-lived idle sessions count against the limit even when doing no work.
- A sudden traffic spike. A burst of requests opens more concurrent connections than the role allows.
How to Reproduce the Error
Set a low connection limit on a test role, then exceed it. As an admin:
ALTER ROLE app_user CONNECTION LIMIT 1;
Open one session as app_user and keep it idle. Then open a second:
-- second psql as app_user
psql "host=localhost user=app_user dbname=appdb"
-- FATAL: too many connections for role "app_user"
The first session occupies the single allowed slot, so the second is rejected.
Diagnostic Commands
Check the configured connection limit for the role (-1 means unlimited):
psql -c "SELECT rolname, rolconnlimit FROM pg_roles WHERE rolname = 'app_user';"
Count how many connections the role currently holds:
psql -c "SELECT usename, count(*) AS conns FROM pg_stat_activity \
GROUP BY usename ORDER BY conns DESC;"
Break those connections down by state to spot idle leaks:
psql -c "SELECT state, count(*) FROM pg_stat_activity \
WHERE usename = 'app_user' GROUP BY state ORDER BY count DESC;"
Find idle and idle-in-transaction sessions for the role with their age:
psql -c "SELECT pid, state, now() - state_change AS idle_for, client_addr \
FROM pg_stat_activity WHERE usename = 'app_user' AND state LIKE 'idle%' \
ORDER BY state_change LIMIT 20;"
Check the cluster-wide limit for context (to confirm it is per-role, not global):
psql -c "SHOW max_connections;"
Find the error frequency in the log:
sudo journalctl -u postgresql --no-pager | grep "too many connections for role" | tail -20
Step-by-Step Resolution
-
Confirm the limit and current usage. Compare
rolconnlimitfrompg_rolesagainst the live count frompg_stat_activity. If usage equals the limit, that is the constraint you are hitting. -
Check for leaks first. Look at the breakdown by state. A large number of
idleoridle in transactionconnections for the role usually means the application is not returning connections to its pool. Fix the leak before raising limits — raising the cap on a leak only delays the failure. -
Right-size the application pool. Ensure the sum of all application instances’ pool sizes for this role is below
rolconnlimit. With four replicas and a limit of 40, each pool should be no larger than about 10. -
Recycle idle connections. Set pool max-idle-time and
idle_in_transaction_session_timeoutso stale sessions are closed and their slots freed. -
Raise the limit if genuinely needed. If the workload legitimately needs more concurrency, raise it:
ALTER ROLE app_user CONNECTION LIMIT 100;(requires superuser or role ownership). Make suremax_connectionsand server memory can accommodate the higher count. -
Introduce a connection pooler. For high-concurrency apps, put PgBouncer in front so hundreds of clients multiplex over a small, bounded number of real role connections, keeping you comfortably under the limit.
Prevention and Best Practices
- Set each role’s
CONNECTION LIMITdeliberately and size application pools so their combined total stays under it with headroom. - Use a connection pooler (PgBouncer in transaction mode) to decouple client concurrency from real backend connections.
- Configure
idle_in_transaction_session_timeoutand pool idle eviction so leaked or idle connections are reclaimed automatically. - Monitor per-role connection counts from
pg_stat_activityand alert before the limit is reached. - Audit application code for connection leaks: always release connections in a
finally/deferblock. - For triage, the free incident assistant can turn a per-role limit log block into a pool-sizing or leak diagnosis.
Related Errors
too many clients already(SQLSTATE53300) — the cluster-widemax_connectionslimit, not per-role.remaining connection slots are reserved for non-replication superuser connections— global slots exhausted, reserved for superusers.FATAL: too many connections for database— the per-databaseCONNECTION LIMITequivalent.sorry, too many clients already— alternate phrasing of the global limit.
Frequently Asked Questions
How is this different from “too many clients already”?
“too many clients already” means the entire cluster has reached max_connections. “too many connections for role” means this specific role has reached its own CONNECTION LIMIT, even though the cluster may have free slots. The fix differs: per-role limits are adjusted with ALTER ROLE, while the global limit is max_connections.
Where is the per-role limit stored?
In the rolconnlimit column of pg_roles (and the underlying pg_authid). A value of -1 means unlimited; any non-negative number is the cap. You set it with ALTER ROLE name CONNECTION LIMIT n.
Should I just raise the limit to make the error stop? Only after confirming there is no connection leak. If idle connections are piling up, raising the limit postpones the failure and wastes server memory. Fix leaks and right-size pools first, then raise the limit if the workload truly needs the concurrency.
Do superusers obey the per-role connection limit?
No. Roles with the SUPERUSER attribute bypass both CONNECTION LIMIT and the reserved-slot logic, which is why superuser connections still succeed when ordinary roles are capped out.
Will a connection pooler solve this? Usually, yes. A pooler like PgBouncer in transaction mode lets many application clients share a small fixed set of role connections, so you stay well under the per-role limit regardless of incoming concurrency.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.