MySQL "Too Many Connections" Error Fix
The "too many connections" error in MySQL means the server has hit its configured connection ceiling and is refusing new clients. Like most databases, this is far more often a sign of connections not being closed properly by an application than a genuine need for more simultaneous capacity.
The Problem
New connection attempts start failing with:
ERROR 1040 (HY000): Too many connections
Existing connections may still work, but anything trying to open a new one — a fresh request, a new worker process, a monitoring tool — gets rejected outright, often during periods of moderate rather than extreme load.
Why It Happens
MySQL enforces a hard limit on simultaneous connections through the max_connections setting, commonly defaulting to 151. The error appears once that ceiling is reached, and the most common underlying causes are:
- The application isn't closing database connections after use, so they accumulate over time — very common with code that opens a connection per request without returning it to a pool
- No connection pooling is configured, so every request opens a brand new connection directly rather than reusing existing ones, which is both slow and doesn't scale
- Multiple application instances (several containers, serverless functions, or worker processes) each maintain their own pool sized for standalone use, and combined they exceed what MySQL allows
- Long-running or stuck queries are holding connections open far longer than expected, preventing them from being released back for reuse
The Fix
First, check how many connections are currently open and where they're coming from:
SHOW PROCESSLIST;
Or, for a summarized view grouped by source:
SELECT user, host, COUNT(*) as connections
FROM information_schema.processlist
GROUP BY user, host
ORDER BY connections DESC;
A large number of connections from the same source, especially many sitting in Sleep state, is the clearest sign of connections not being released properly, rather than genuine concurrent demand.
If you're not already using connection pooling at the application level, add it — this is the standard fix rather than simply raising the limit. Most frameworks and ORMs support this natively; for example, in a Node.js app using mysql2:
const pool = mysql.createPool({
host: 'localhost',
user: 'app_user',
connectionLimit: 10,
});
With pooling configured, your application reuses a fixed, small number of actual connections instead of opening a new one for every request, which is both faster and dramatically reduces the chance of hitting the connection ceiling.
Make sure connections are explicitly released back to the pool after each unit of work, rather than left open implicitly — a pool only helps if connections are actually returned to it:
const conn = await pool.getConnection();
try {
// queries here
} finally {
conn.release();
}
Only as a last resort, once you've confirmed pooling is properly configured and connections are being released correctly, consider raising max_connections — but be aware each additional connection consumes memory, so this isn't a free fix:
SET GLOBAL max_connections = 300;
This change is temporary until restart; to persist it, add max_connections = 300 under the [mysqld] section of your MySQL configuration file.
Still Not Working?
If connections keep piling up even with pooling in place, look for long-running or stuck queries that never complete. You can identify and terminate a specific problematic connection manually while you investigate the root cause in the application code:
SHOW PROCESSLIST;
KILL <connection_id>;
It's also worth checking whether multiple separate services are all connecting to the same database independently, each with their own pool sized without awareness of the others — reviewing the grouped connection query above by application name or source IP usually makes this kind of hidden multiplication obvious.
If you're running MySQL inside a container with a fixed memory limit, keep in mind that raising max_connections significantly increases baseline memory usage, since MySQL allocates memory per connection regardless of whether it's actively running a query. In memory-constrained environments, fixing the underlying connection leak or adding pooling is almost always a better long-term solution than simply raising the ceiling repeatedly whenever the error reappears.
Finally, if the errors correlate with a specific deploy or traffic spike rather than a slow gradual buildup, check whether a recent code change introduced a new code path that opens connections without going through your existing pool — a single new feature or background job added outside the normal request flow is a common source of a sudden shift from "stable for months" to "hitting the limit regularly."