Your application is throwing ERROR 1040 (HY000): Too many connections and new clients cannot reach the database. MySQL has reached max_connections and is refusing every additional login. This is usually a fast, recoverable incident once you can get a session open. The goal below is to stabilize first (get back in and shed load), then diagnose what is holding the connections, then fix the real cause so it does not repeat within the hour.
What this error means
MySQL enforces a hard ceiling on concurrent client connections set by the max_connections system variable. When the number of open connections reaches that ceiling, the server rejects any new connection with error 1040. It is not a crash and not corruption: the server is healthy and simply full. Critically, MySQL reserves one additional slot above the limit for a user with the SUPER or CONNECTION_ADMIN privilege, so an administrator can still log in to investigate even while ordinary clients are locked out.
Common causes
- An application connection pool sized too large (many app instances, each with its own pool, multiplying total connections beyond what MySQL allows).
- A missing or misconfigured pool, so the app opens a fresh connection per request and never reuses or closes them.
- Idle connections left in the
Sleepstate that are not reaped, becausewait_timeoutandinteractive_timeoutare set very high. - Long running or stuck queries holding connections open (a slow report, a lock wait, or a runaway migration).
- A traffic spike or retry storm that briefly needs more connections than the server is configured for.
max_connectionsset far too low for the workload, or lowered by a default parameter group on a small instance.
How to fix it
Stabilize: get in and shed load
- Connect using an admin account that holds
SUPERorCONNECTION_ADMIN. That account uses the reserved slot, so it works even when the limit is hit. On RDS or Aurora, use the master user.
mysql -h 127.0.0.1 -u admin -p
- See who is connected and in what state.
SHOW PROCESSLIST;
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
- Kill the clearest offenders to free slots immediately: long running queries and stale sleeping sessions. Replace the id with the values from the process list.
KILL 12345;
To find sleeping connections older than 300 seconds without scanning by eye, use performance_schema (or information_schema.PROCESSLIST on older servers):
SELECT id, user, host, time, command, info
FROM information_schema.PROCESSLIST
WHERE command = 'Sleep' AND time > 300
ORDER BY time DESC;
Diagnose: find what is holding connections
- Decide whether this is leaked idle connections (many rows in
Sleep) or genuine concurrency (manyQueryrows). Group them:
SELECT user, host, command, COUNT(*)
FROM information_schema.PROCESSLIST
GROUP BY user, host, command
ORDER BY COUNT(*) DESC;
A large Sleep count from one app host points to a pool that never closes connections. A large Query count points to slow queries or a pool sized too high.
Fix: raise the ceiling carefully, then fix the cause
- If you need immediate headroom, raise the limit at runtime. This takes effect without a restart but does not survive one.
SET GLOBAL max_connections = 300;
- Make it persist. On self managed MySQL, set it in
my.cnfunder[mysqld]and also tighten idle timeouts so sleeping connections get reaped:
[mysqld]
max_connections = 300
wait_timeout = 300
interactive_timeout = 300
On RDS or Aurora, change these in the DB parameter group instead of my.cnf. max_connections there often defaults to a formula based on instance memory, so a larger instance class may be the real lever.
- Fix the source. Cap the application pool so that (app instances x pool size) stays comfortably under
max_connections, and ensure connections are returned to the pool. For high fan out, put a pooler such as ProxySQL in front of MySQL so many app connections share a small set of backend connections.
How to prevent it
- Size pools by the formula: total app connections must stay below
max_connections, with margin for admin access and cron jobs. - Keep
wait_timeoutandinteractive_timeoutmoderate so idle connections are reclaimed. - Alert on
Threads_connectedat roughly 80 percent ofmax_connections, before rejection starts. - Put a connection pooler (ProxySQL, or a language level pool) between the app and the database at scale.
- Remember each connection costs memory, so validate that the host or instance class has headroom before raising the limit.
When to call a senior engineer
Call for help if killing sessions frees slots but they refill within seconds (a live leak or retry storm you cannot locate), if raising max_connections risks an out of memory kill on a small host, or if the connections are all in Query state on locked rows and you are unsure which to kill safely. Erzon can join a live incident, identify the leaking client, and size the pool and the instance so error 1040 stops recurring.
Related errors we fix
ERROR 1045 (28000): Access denied for user Fix this error → MySQL ERROR 1114 (HY000): The table is full Fix this error → MySQL ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction Fix this error → MySQL ERROR 1206 (HY000): The total number of locks exceeds the lock table size Fix this error → Want a senior engineer to just fix it?
Paste this exact error into the form. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.
Book a fix