MySQL max_user_connections Error: Causes and the Fix

· 7 min read · 26 views · Getwebup

Your site throws "Error establishing a database connection," but when you check the MySQL error log or a debug query, the real message is ERROR 1226 (42000): User 'dbuser' has exceeded the 'max_user_connections' resource (current value: 20). If that looks familiar, you're not hitting a server-wide MySQL limit — you're hitting a per-account cap, and the fix is completely different from the usual "raise max_connections" advice.

What max_user_connections actually is

MySQL has two separate connection ceilings, and mixing them up wastes a lot of troubleshooting time:

LimitScopeWho sets itTypical error
max_connectionsWhole MySQL server, all users combinedServer admin, in my.cnfERROR 1040: Too many connections
max_user_connectionsOne specific database user onlyPer-account grant, or a WHM/cPanel resource limitERROR 1226: User has exceeded the 'max_user_connections' resource

On shared cPanel hosting, every account usually gets its own database user with its own cap on simultaneous connections — often somewhere between 10 and 25, depending on the plan. The rest of the server can be sitting nearly idle and you'll still get locked out the moment your site alone opens more connections than your account is allowed.

Reading the error, word by word

The full message usually looks like one of these:

ERROR 1226 (42000): User 'dbuser' has exceeded the 'max_user_connections' resource (current value: 80)
could not connect to the database 3306. user 'dbuser' has exceeded the 'max_user_connections' resource (current value: 80)
  • 1226 is MySQL's error number for a per-user resource limit being hit. It is not a password or permissions problem.
  • user 'dbuser' is the database user your site logs in as, from wp-config.php or your app's config. Only that user is being refused; other sites on the same server keep working.
  • (current value: 80) is the limit itself, not the number of connections open right now. This user may hold at most 80 connections at once, and a new one was refused because all 80 were in use.
  • could not connect to the database 3306 is your application's own wording around the same MySQL error; 3306 is simply the port MySQL listens on. The cause and the fix are the same as for the plain 1226 message.

Why it happens

Traffic burst on a low-limit plan

A sale, a newsletter blast, or a bot crawl can spin up more concurrent PHP processes than usual. Each one opens its own MySQL connection, and on a plan capped at 15–20 connections per user, that's not much headroom. Entry-level shared hosting plans are sized for typical traffic, not spikes, precisely because most accounts on the server never come close to their cap — until one day yours does.

Connections that don't close cleanly

Persistent connections (mysqli_connect with the p: prefix, or some poorly written plugins) can hang around longer than they should. So can PHP-FPM workers that stay busy on a slow page and hold their DB connection the whole time. A single slow query — an unindexed WooCommerce lookup, say — can tie up a connection for seconds instead of milliseconds, and if enough requests pile up behind it, you run out of slots even though total traffic looks unremarkable in your analytics.

Multiple sites sharing one database user

If you've pointed two or three WordPress installs at the same MySQL user to save on account limits, their connection counts stack. One site's traffic spike can lock out the others.

A runaway cron job or import script

WP-CLI loops, migration scripts, or a cron job that fires every minute and doesn't release its connection properly will quietly eat your quota in the background, so the error shows up even during low traffic.

Confirm it's really this, not the server-wide limit

Don't guess — check. If you have SSH or Terminal access in cPanel:

mysql -u your_db_user -p -e "SHOW VARIABLES LIKE 'max_user_connections';"
mysql -u your_db_user -p -e "SELECT COUNT(*) FROM information_schema.processlist WHERE user='your_db_user';"

If the second number is sitting right at or above the first, that's your answer. On shared hosting without shell access, check cPanel → MySQL Databases or the resource usage panel — some hosts surface the current connection count there, or you can just check the exact wording of the error your site is throwing. "max_user_connections" in the message means per-user, not server-wide.

See what the open connections are doing

Knowing the count is at the limit is only half the answer. This groups the connections by what they are doing, so the pattern is obvious:

SELECT command, state, COUNT(*) AS connections, MAX(time) AS longest_seconds
FROM information_schema.processlist
WHERE user = 'your_db_user'
GROUP BY command, state
ORDER BY connections DESC;

A database user can always see its own connections, so this also works from phpMyAdmin's SQL tab on shared hosting. If the limit is so full that even this query can't connect, run it as root on a VPS (root sees every user's connections) or retry in a few seconds.

  • Mostly Sleep, with a large longest_seconds: connections are opened and never closed — persistent connections, or code that doesn't close them. See "Fix what's actually eating connections" below.
  • Mostly Query, several seconds each: slow queries are piling up and holding connections while they run. Find them with the MySQL slow query log.
  • A steady count at the limit whenever traffic rises: more PHP workers than the limit allows. Tune the PHP-FPM pool to match.

For immediate relief you can close your own idle connections with KILL <id>;, taking the IDs from SHOW PROCESSLIST;. That frees slots at once, but they fill up again until the cause is fixed.

How to fix it

On shared cPanel hosting (no root access)

You can't edit my.cnf here — the limit is enforced by the hosting account's resource package. Two real options:

  1. Ask your host to raise the per-account MySQL connection limit. On Getwebup this is a quick change on our side once we confirm it won't affect neighboring accounts on the same server.
  2. Reduce how many connections your site opens at once — see the fixes below before assuming you need a bigger limit.

On a VPS or dedicated server with root MySQL access

You can set the per-user limit directly:

ALTER USER 'your_db_user'@'localhost' WITH MAX_USER_CONNECTIONS 50;
FLUSH PRIVILEGES;

On older MySQL/MariaDB versions where ALTER USER ... WITH isn't supported, use:

GRANT USAGE ON your_database.* TO 'your_db_user'@'localhost' WITH MAX_USER_CONNECTIONS 50;

Set it high enough to cover real peak traffic, but remember it's still bounded by the server-wide max_connections — raising one without checking the other just moves the wall.

Fix what's actually eating connections

Raising the cap buys time; it doesn't fix a leak. Check these first:

  • PHP-FPM pool size. If pm.max_children in your PHP-FPM pool config is set much higher than your MySQL user's connection limit, every busy moment will hit the wall. Bring them in line.
  • Persistent connections. If a plugin or custom code uses mysqli_pconnect or PDO persistent mode, connections can sit open between requests. Turning persistent connections off usually clears this up fast.
  • Object caching. A Redis or Memcached object cache in front of WordPress cuts the number of database round-trips per page load significantly, which lowers concurrent connection pressure during traffic spikes.
  • Cron and import scripts. Make sure long-running WP-CLI or migration scripts explicitly close their MySQL connection when done, and don't schedule the same heavy cron job to overlap itself.

Prevention checklist

  • Give each site its own database user instead of sharing one across multiple installs.
  • Match your PHP-FPM pm.max_children to what your MySQL connection limit can actually support.
  • Add an object cache (Redis or Memcached) if your site does more than a trickle of traffic.
  • Monitor connection counts before a planned traffic event — a sale, a launch, a press mention — and ask your host to raise the limit in advance rather than mid-outage.
  • Avoid persistent MySQL connections unless you've specifically tuned your stack for them.

If you're on Getwebup hosting and keep hitting this ceiling even after cleaning up connection usage, it's usually a sign your plan's resource limits no longer match your traffic — worth a quick chat with support before it becomes a recurring outage.

Questions people actually ask