DEV Community

Getwebup
Getwebup

Posted on Originally published at getwebup.in

MySQL max_user_connections Error: Causes and the Fix

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:

Limit Scope Who sets it Typical error
max_connections Whole MySQL server, all users combined Server admin, in my.cnf ERROR 1040: Too many connections
max_user_connections One specific database user only Per-account grant, or a WHM/cPanel resource limit ERROR 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)
Enter fullscreen mode Exit fullscreen mode
  • 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';"
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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.

FAQ

What's the difference between max_connections and max_user_connections?

max_connections is a server-wide MySQL setting that caps total connections from every user combined. max_user_connections caps connections from one specific database user, regardless of how busy the rest of the server is. On shared cPanel hosting, you'll usually hit the per-user limit long before the server-wide one.

Can I fix this myself on shared hosting?

You can't edit the limit directly without root access, but you can reduce how many connections your site opens at once by tuning PHP-FPM, disabling persistent connections, and adding an object cache. If that's not enough, ask your host to raise the per-account limit.

Will restarting MySQL fix it?

It clears the immediate backlog by closing all open connections, but it's a temporary fix. If the underlying cause — a leak, an undersized limit, or an overlapping cron job — isn't addressed, the error comes back.

Does WordPress show a specific error for this, or just the generic database message?

WordPress shows the same generic 'Error establishing a database connection' screen regardless of the cause. You have to check the MySQL error log, enable WP_DEBUG, or query the database directly to see the actual max_user_connections message.

How do I know what limit my hosting plan gives me?

Run SHOW VARIABLES LIKE 'max_user_connections'; against your database user if you have any command-line or phpMyAdmin SQL access. If you can't run queries, check your hosting plan's resource limits page or ask support directly.

What does 'current value: 80' mean in the max_user_connections error?

It is the limit, not the live count. The database user may hold at most 80 connections at the same time, and the error appears when one more is attempted. On shared hosting your host sets that number.

Why does the error start with 'could not connect to the database 3306'?

That part is your application's own message, and 3306 is the port MySQL listens on. Underneath it is the same MySQL error 1226, so the cause (too many open connections for one database user) and the fix are the same.


Originally published on the Getwebup blog.

Top comments (0)