Guide Databases & MySQL

How to fix a "too many connections" error

The database has a limit on simultaneous connections, and something is holding on to more of them than it should.

Updated 7 min read Intermediate

"Too many connections" is MySQL refusing a new connection because it has already reached the maximum number it is configured to allow at once. It is not damage, and it usually is not a sign the database itself is struggling, though it can look exactly like that from the outside. It means the ceiling has been reached, and something is holding open more connections than the site's normal traffic should need.

What a "connection" actually is here

Every time a script, an application, or an administrative tool talks to the database, it opens a connection, uses it, and is supposed to close it again. MySQL is configured with a maximum number it will allow open at the same time, across every application and every user on the server. Once that number is reached, the next attempt to connect is refused outright, rather than queued, which is why the error tends to appear suddenly rather than build up gradually.

Seeing what is actually connected

Before changing anything, look at what is actually holding connections open. In phpMyAdmin's SQL tab, or from any connected client with sufficient privileges, run:

SHOW PROCESSLIST;

This lists every current connection, including which database it is using, how long it has been open, and what it is doing. A long list of connections sitting idle, or several running the exact same query, points at the cause far faster than guessing does. To see how many connections are currently open against the total allowed:

SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';

If Threads_connected is regularly sitting close to max_connections, that confirms the limit really is the bottleneck rather than something else producing a similar-looking error.

The usual causes, and which one you likely have

A genuine spike in traffic

A sudden increase in visitors, each opening their own connection through the application, can exhaust the limit on a busy site even when every connection is being closed correctly. The tell here is a processlist full of short-lived, varied queries rather than the same handful of connections sitting idle.

Connections that are never closed

A script that opens a database connection and does not close it when it finishes, particularly one that runs frequently or in a loop, accumulates open connections faster than they are released. This is one of the most common causes on smaller sites, because it does not need much traffic at all to trigger it, and it tends to show up as the same code path holding several connections open in the processlist at once.

Persistent connections that are not being reused as intended

Persistent connections are meant to be kept open and reused between requests to avoid the overhead of reconnecting each time, but a misconfigured pool of them can end up holding far more connections open than the traffic actually needs, especially under load. If your application is configured to use persistent connections, this is worth checking specifically.

Overlapping scheduled jobs

A cron job that takes longer to run than the interval it is scheduled on will eventually overlap with itself, each overlapping run opening its own connection on top of the last. This builds gradually rather than appearing all at once, and the processlist will show the same scheduled task's query appearing more than once at the same time.

A plan-level connection limit

Shared hosting plans commonly cap the number of simultaneous database connections a single account can use, separately from the server-wide MySQL limit, to keep one account from affecting others on the same server. If everything above checks out and the site is simply busier than it used to be, this is worth checking directly in your control panel or by contacting your host.

Fixing it depending on what you found

  • Close connections explicitly in code. Make sure every script that opens a database connection also closes it once it is finished, rather than relying on the process ending to release it eventually.
  • Stagger or lengthen the interval on overlapping cron jobs. If a scheduled task regularly runs longer than its own interval, either give it more time between runs or make it detect and skip a run that is already in progress.
  • Reduce the number of queries a page needs. Fewer queries per request generally means fewer or shorter-lived connections. Finding the query slowing your site down and optimising a MySQL database both help here even though neither is written specifically about connection limits.
  • Add caching in front of the database. A page cache or object cache serving repeat requests without touching the database at all removes connections from the count entirely rather than making each one shorter.
  • Raise the limit, if the traffic behind it is genuine. If none of the above applies and the site is simply handling more legitimate traffic than before, contact us about raising the connection allowance on your plan rather than working around a limit that no longer fits.
Ending a connection manually is a short-term relief, not a fix

You can end a specific connection from the processlist with KILL followed by its ID, which is sometimes useful to clear a single stuck connection immediately. It does nothing about whatever is causing connections to pile up in the first place, and killing a connection that is mid-write can leave a query incomplete. Use it to relieve pressure while you investigate, not as the actual solution.

If the error only appears intermittently

An error that comes and goes, rather than staying constant, usually points at traffic spikes or overlapping jobs rather than a connection that is permanently leaked, since a genuinely leaked connection tends to accumulate until the limit is hit and stays hit. Note what time the error tends to appear and cross-reference it against your cron schedule and your traffic patterns before assuming the worst.

If you have worked through this and still cannot identify the source, contact us with a note of when the error occurs and, if you have it, the output of SHOW PROCESSLIST from the time it happened, and we can look at the account's connection activity directly.

Related reading