The error everyone fears
You refresh your WordPress site and instead of your home page, you see this:
Error establishing a database connection
Nothing else. No stack trace, no log line, no hint about what's wrong. This is the most feared error message in WordPress β and the most misunderstood. It almost always has one of five specific causes, and once you know how to look, you find the cause in under 5 minutes.
This article walks through what the error actually means, the five technical causes, the diagnostic flow we use, and how to prevent it from happening again.
What the error actually means
When WordPress boots, the very first thing it tries to do is connect to MySQL. The connection uses four pieces of information from your wp-config.php file:
define('DB_HOST', 'localhost');
define('DB_USER', 'wp_user');
define('DB_PASSWORD', 'pass123');
define('DB_NAME', 'wordpress_db');WordPress passes these to PHP's MySQLi extension. If anything fails β wrong credentials, MySQL not running, network unreachable, too many existing connections β PHP returns an error and WordPress catches it and shows the generic "Error establishing a database connection" message.
The genericity is deliberate. Leaking the real error to visitors would help attackers. The real error is in the server log; visitors only see the generic.
Cause 1 β Wrong credentials
The most common cause by far. One of DB_HOST, DB_USER, DB_PASSWORD, or DB_NAME no longer matches what MySQL accepts.
When this happens
- Someone rotated the MySQL password but forgot to update
wp-config.php - A migration to a new host where the credentials are different
- A hosting panel auto-rotated credentials for security
- A typo introduced during a manual
wp-config.phpedit - File restore from a backup taken when credentials were different
How to verify
Connect to MySQL directly with the same credentials from the same server:
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD -D $DB_NAMEIf this command succeeds, credentials are correct and the issue is elsewhere. If it fails, you know which credential is wrong by the error message (Access denied for user..., Unknown database...).
Fix
Update wp-config.php with the correct values. If you don't know the correct values, get them from your hosting panel (cPanel β MySQL Databases) or your password manager.
Cause 2 β MySQL is not running
The MySQL service itself is down. Less common than credential issues, but more dramatic.
When this happens
- Server out of memory and Linux OOM killer terminated MySQL
- A MySQL crash caused by a corrupt InnoDB tablespace
- Manual
systemctl stop mysqlfollowed by forgetting to restart - A disk-full condition preventing MySQL from writing
- Server reboot where MySQL is not configured to auto-start
How to verify
On the server:
systemctl status mysql # or mariadb, or mysqld
ps aux | grep -i mysql
ss -tlnp | grep 3306 # is anything listening on the MySQL port?Fix
systemctl start mysql
journalctl -u mysql -n 50 # check why it stoppedIf MySQL won't start, the journal log tells you why. Common reasons: corrupt table requiring --innodb-force-recovery, ran out of disk space, missing mysql.sock file.
Cause 3 β Too many connections
MySQL has a hard cap on simultaneous connections (max_connections, default 151). When the cap is hit, new connection attempts fail.
When this happens
- A traffic spike where many concurrent visitors all need DB connections
- A plugin leaking connections (failing to close after use)
- Multiple WordPress sites on the same MySQL server, sharing the limit
- Long-running queries holding connections open while new ones queue up
- A failed deploy that left worker processes orphaned
How to verify
mysql -e "SHOW STATUS LIKE 'Threads_connected';"
mysql -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -e "SHOW PROCESSLIST;"If Threads_connected is near max_connections, you have a saturation problem.
Fix
Short term: increase max_connections in my.cnf:
[mysqld]
max_connections = 300Then restart MySQL. Note: increasing this consumes more memory. Each connection costs roughly 1MB at minimum, sometimes more.
Long term: find what's leaking. SHOW PROCESSLIST shows current queries; look for queries in Sleep state for long periods β that's a leak.
Cause 4 β User locked out by MySQL
MySQL can lock a user account if its password fails too many times (when password_history and password_reuse_interval are configured) or if the user is explicitly suspended.
When this happens
- A brute-force attempt on the database account
- A misconfigured backup script using wrong credentials and repeatedly failing
- A security plugin rotating passwords and not updating the database user
- A hosting provider's automated security response
How to verify
mysql -e "SELECT user, host, account_locked FROM mysql.user WHERE user='wp_user';"Fix
ALTER USER 'wp_user'@'localhost' ACCOUNT UNLOCK;Plus identify and fix what was triggering the lockout in the first place.
Cause 5 β Network or socket issue
DB_HOST of localhost uses a Unix socket; 127.0.0.1 uses TCP. If the socket file is missing or the TCP port is unreachable, the connection fails even though MySQL is running.
When this happens
- MySQL was reinstalled with a different socket path
- The socket file got deleted (cleanup script gone wrong)
- A firewall rule is blocking port 3306 on TCP
- Remote MySQL host is unreachable (network outage)
DB_HOSTset to a hostname that doesn't resolve
How to verify
# Find the actual MySQL socket
mysql -e "SHOW VARIABLES LIKE 'socket';"
# Check if it exists
ls -la /var/run/mysqld/mysqld.sock
# TCP connectivity test
nc -zv $DB_HOST 3306Fix
For Unix socket issues: update DB_HOST in wp-config.php to the explicit socket path:
define('DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock');Or switch to TCP:
define('DB_HOST', '127.0.0.1:3306');For TCP issues: fix firewall, fix DNS, or move the database to a reachable host.
The 5-minute diagnostic flow
When the error appears, run this sequence:
# Step 1 β Can MySQL even be reached?
mysql -e "SELECT 1;" 2>&1
# If step 1 fails with "Access denied":
# β Credential issue (Cause 1) or locked user (Cause 4)
# If step 1 fails with "Can't connect":
# β MySQL down (Cause 2) or socket/network issue (Cause 5)
# If step 1 fails with "Too many connections":
# β max_connections saturation (Cause 3)
# Step 2 β Confirm WP credentials work
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" -D "$DB_NAME" -e "SELECT 1;"
# Step 3 β Check WP-CLI from the WordPress directory
cd /var/www/yoursite && wp db checkThese three steps narrow down the cause every time.
Prevention checklist
Once you've fixed the immediate problem, harden against recurrence:
- Document the database credentials in your password manager, not just
wp-config.php - Set
auto-restartfor MySQL:systemctl enable mysql - Configure MySQL
max_connectionsbased on real load + 50% headroom - Add monitoring on the
Threads_connectedMySQL variable; alert at 80% of max - Lock down outbound port 3306 access (only your WordPress server, not the public internet)
- Schedule daily backups of
wp-config.phpseparately from the rest (it contains the credentials needed to restore everything else)
Common mistakes when diagnosing
- Assuming the issue is WordPress when it's MySQL β WordPress is reporting the error, but the cause is on the database side
- Restarting MySQL without checking why it stopped β masks the underlying issue, will happen again
- Increasing `max_connections` to 1000 β solves the symptom, leaves the connection leak
- Editing `wp-config.php` without backing it up first β one typo and you lose access to all backups too
- Resetting MySQL password to fix "Access denied" β only valid if you confirmed credentials are wrong; otherwise breaks more things
When to call a specialist
The "Error establishing a database connection" message is solvable in 5 minutes for someone who has seen all five causes. It's solvable in 5 hours for someone seeing it for the first time. For business sites, the difference between 5 minutes and 5 hours is the difference between negligible loss and significant revenue loss.
Database connection emergency? We're online within minutes. For deeper repair, see database connection failure and corrupted table recovery.

