Your site is up, the database exists, wp-config.php has the right credentials — and yet every so often, a page load fails with Error establishing a database connection, or if you're looking at it from the command line, something blunter: ERROR 1040 (HY000): Too many connections. This isn't the same problem as bad credentials or a corrupted database. It's a limit being hit, and once you know what to check, it's usually a five-minute fix.
Symptom: What This Error Actually Looks Like
A few places this shows up:
- WordPress front-end throws a generic database connection error, but only sometimes — often during traffic spikes, not consistently.
- phpMyAdmin refuses to open, or hangs, with
#1040 - Too many connections. - SSH into the server and run
mysql -u root -p, and you get the same 1040 error before you even reach a prompt. - Your application logs (PHP error log, Laravel log, custom app log) show
PDOException: SQLSTATE[HY000] [1040] Too many connections.
The key giveaway is that it's intermittent and tied to load. A permanently broken database connection (wrong password, wrong host, dropped table) fails every single time. This one comes and goes as connection counts rise and fall.
Cause: Why MySQL Is Refusing New Connections
MySQL (or MariaDB, same idea) has a hard cap on how many simultaneous client connections it will accept, controlled by the max_connections variable. Once that cap is hit, every new connection attempt gets rejected — including the one your WordPress site or your own login attempt is trying to make. A few common reasons you hit the ceiling:
- The default is just low for your traffic. Shared cPanel hosting environments often ship with
max_connectionsset conservatively (100-150) to protect the whole server from any one account. - Connections aren't being closed properly. A plugin, a poorly written script, or a cron job that opens a database handle and never releases it will slowly eat up the pool.
- Traffic spikes. A sale, a viral post, or a bot crawl can multiply concurrent page loads, and each one opens its own connection (sometimes several, if the site queries multiple databases).
- WP-Cron pile-ups. If wp-cron.php is triggered on every page load and scheduled tasks are backed up, you can get a burst of simultaneous cron connections on top of normal visitor traffic.
- No caching layer. Every single request hitting the database directly, with no object cache in front of it, multiplies connection pressure for no good reason.
Fix: Diagnose First, Then Adjust
Don't just crank up max_connections blindly — check what's actually happening first. Log in via SSH (or use the Terminal app in cPanel if you don't have shell access) and run:
mysql -u root -p -e "SHOW STATUS LIKE 'max_used_connections'; SHOW VARIABLES LIKE 'max_connections';"
If max_used_connections is consistently close to or above max_connections, the limit itself is the bottleneck. If it's well below the limit but you're still getting errors, something else is grabbing connections in bursts — check SHOW PROCESSLIST; to see what's actually connected right now and how long each query has been running.
SHOW PROCESSLIST;
Look for queries stuck in Sleep state for a long time, or the same query repeated dozens of times — that's usually a plugin or script leaking connections rather than a genuine traffic problem. You can kill a specific stuck connection with:
KILL <process_id>;
That buys you breathing room immediately, but it's a bandage, not a fix. Once you've identified the pattern, here's how to actually address it:
On cPanel / Shared Hosting
- If you have WHM access, go to WHM » Service Configuration » MySQL/MariaDB Configuration and raise
max_connectionsin small steps (e.g. 150 to 250), then restart the service. - If you're on shared hosting without WHM access, this is a conversation with your host's support team — ask them to check your account's current connection usage and raise the limit if the server has headroom. Most hosts, SkyServer included, can bump this per-account without a full server change.
- Check whether a specific plugin is the culprit before asking for a bump. Deactivate suspect plugins one at a time and watch
SHOW PROCESSLISTduring a normal traffic window.
On a VPS You Manage Directly
- Edit your MySQL/MariaDB config file, typically
/etc/my.cnfor/etc/mysql/mariadb.conf.d/50-server.cnf, and add or edit under[mysqld]:
[mysqld]
max_connections = 200
wait_timeout = 60
interactive_timeout = 60
Lowering wait_timeout matters as much as raising max_connections — it forces MySQL to close idle sleeping connections faster instead of letting them sit around occupying a slot for 8 hours (the default). Then restart the service:
sudo systemctl restart mysql
# or, on some distros:
sudo systemctl restart mariadb
Before you raise max_connections too far, do the math against available RAM. Each connection reserves memory (thread stack, buffers), so on a 2GB VPS, pushing max_connections to 500 can starve MySQL of memory under load and trigger swapping or an OOM kill — which is a worse outage than the original error. A rough rule of thumb: keep max_connections proportional to what your RAM can actually back, not just what feels safe.
| Environment | Typical default | Safe first bump |
|---|---|---|
| Shared cPanel hosting | 100-151 | Ask host to raise to 200-250 |
| Small VPS (2GB RAM) | 151 | 200, with wait_timeout lowered |
| VPS (4-8GB RAM) | 151 | 300-500, monitored |
Prevention: Stop This From Coming Back
- Add an object cache. Redis or Memcached in front of WordPress (via a plugin like Redis Object Cache) cuts database hits dramatically, since repeat queries get served from memory instead of opening a new connection.
- Fix wp-cron. Disable the default trigger-on-page-load behavior in
wp-config.phpand run it via a real system cron job every few minutes instead — this avoids cron connections piling up during traffic spikes. - Audit plugins periodically. A plugin that queries the database on every request without caching is a common silent cause of connection pressure. Query Monitor (a free WordPress plugin) will show you exactly which plugins are heaviest.
- Set a sane wait_timeout. Don't let idle connections sit around for hours; 60 seconds is plenty for most sites.
- Watch it, don't wait for it. If your VPS plan includes monitoring, set an alert on
Threads_connectedapproachingmax_connectionsso you know before visitors do. - Consider ProxySQL or a connection pooler if you're running a high-traffic site with multiple app servers hitting one database — it multiplexes many app-level connections over fewer real MySQL connections.
Frequently Asked Questions
Is this the same as WordPress's "Error establishing a database connection"?
Not always. That generic WordPress message can mean several things: wrong credentials in wp-config.php, a corrupted database, the MySQL service being down, or — this specific case — the connection limit being maxed out. Check your error log or run a direct MySQL command from SSH to see if you get the specific 1040 Too many connections message; that confirms it's a limit issue, not a config or corruption problem.
Will raising max_connections fix it permanently?
It buys headroom, but if the real cause is a connection leak (a plugin or script not closing connections properly) or unbounded traffic growth, you'll hit the new, higher ceiling eventually too. Treat a bump as relief while you find and fix the underlying driver.
Can I just restart MySQL to clear it temporarily?
Yes, restarting the MySQL/MariaDB service will immediately drop all open connections and free the pool, and it's a reasonable emergency step if your site is down right now. But it's not a fix — whatever caused the pileup will start refilling the pool again unless you address it.
How do I know if it's a shared hosting limit or my own site's fault?
Run SHOW PROCESSLIST; during the error window. If you see dozens of connections all from your own database user and application, it's your site's behavior. If you don't have visibility into other accounts on the server (normal on shared hosting) and the limit seems too low for even modest traffic, ask your host to check server-wide connection headroom.
Does this affect email or FTP too?
No — max_connections in MySQL only governs database connections. Email and FTP have their own separate connection and rate limits, configured independently in the mail server and FTP daemon.
