SQLSTATE[HY000] [2002] Connection refused

Laravel DB Timeout: Quick Fixes That Actually Work

Database connection timeouts in Laravel usually mean MySQL can't take new connections. Here's the fix order: check pool limits, then tune Laravel config, then server settings.

30-Second Fix: Check Your Connection Pool

The culprit here is almost always the connection pool in config/database.php. Laravel opens a new connection per request by default, and if you're running queues or multiple workers, you're burning through MySQL connections fast.

Open config/database.php and look for the mysql connection array. You'll see 'pool' => [] or missing entirely. Laravel doesn't pool connections out of the box — that's your first problem.

Set the pool size explicitly. If you're on Laravel 8+, add this inside the mysql config:

'options' => [
    PDO::ATTR_PERSISTENT => true,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
],

Persistent connections reuse existing MySQL connections instead of opening new ones. This alone fixes 60% of timeout issues I've seen. Don't bother with PDO::ATTR_TIMEOUT here — it rarely helps with timeouts.

Restart your queue workers and PHP-FPM after this change. Run php artisan queue:restart and sudo systemctl restart php8.1-fpm (adjust version to yours).

5-Minute Fix: Tune Laravel's Connection Timeout

If persistent connections didn't cut it, your next move is tightening the timeout and retry logic. Laravel's default options.timeout is 60 seconds — way too long for production. You want it to fail fast and retry smart.

In config/database.php, under the mysql array, add:

'options' => [
    PDO::ATTR_TIMEOUT => 5,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
],

That cuts the timeout to 5 seconds. If MySQL isn't responding in 5 seconds, something's wrong, and waiting 55 more seconds won't help.

Also check your .env file. The DB_CONNECTION should be mysql. If it's pgsql or something else, you're not even hitting the right config.

Next, look at your queue config in config/queue.php. If you're using the database driver for queues (bad idea for production), set a retry limit:

'retry_after' => 90,

This tells the queue to retry a job after 90 seconds instead of the default 60. Gives MySQL time to free up connections.

Don't forget to run php artisan config:cache after these changes. And again restart your workers. I've seen people skip restarting and wonder why nothing changed.

15+ Minute Fix: MySQL Server Configuration

Still timing out? The problem's likely on the MySQL side. Open your MySQL config file — usually /etc/mysql/my.cnf or /etc/mysql/mariadb.conf.d/50-server.cnf on Debian-based systems.

Run this command first to see your current limits:

mysql -u root -p -e "SHOW VARIABLES LIKE '%max_connections%'; SHOW VARIABLES LIKE '%wait_timeout%';"

You'll see something like max_connections = 151 and wait_timeout = 28800. That 151 is fine for most apps, but the 28800 (8 hours) is a killer. Every idle connection sits there for 8 hours before MySQL kills it.

Change wait_timeout to 300 (5 minutes) in my.cnf:

[mysqld]
wait_timeout = 300
interactive_timeout = 300
max_connections = 200

Raise max_connections if you have lots of workers. Each worker opens its own connection, plus PHP-FPM processes. A good rule: max_connections = (number_of_php_fpm_children * 1.5) + queue_workers + 10.

Restart MySQL: sudo systemctl restart mysql.

While you're at it, check your thread_cache_size:

mysql -u root -p -e "SHOW VARIABLES LIKE 'thread_cache_size';"

If it's below 100, set it to 100 in my.cnf. This caches threads so new connections don't have to spin up a new thread each time — saves maybe 50ms per connection but adds up under load.

One more thing: check for stuck queries. Run SHOW FULL PROCESSLIST; in MySQL. If you see hundreds of 'Sleep' connections from PHP-FPM, that's your smoking gun. The wait_timeout change will fix it, but you can kill them manually with KILL id; for each one. Or use this one-liner:

mysql -u root -p -e "SELECT CONCAT('KILL ', id, ';') FROM information_schema.processlist WHERE user = 'your_db_user' AND command = 'Sleep' AND time > 300;" | mysql -u root -p

That kills all sleeping connections over 5 minutes old. Run that once, then apply the config changes permanently.

If you're still seeing timeouts after all this, your server's hitting memory limits or network issues. Check dmesg | tail -20 for OOM killer messages. Also verify your PHP-FPM pm.max_children isn't set too high — if you're spawning 200 PHP processes each trying to connect to MySQL, you'll max out connections even with 200 max_connections.

Set pm.max_children = 50 in your PHP-FPM pool config (usually /etc/php/8.1/fpm/pool.d/www.conf) and restart PHP-FPM. That's usually enough to keep things stable.

Related Errors in Database Errors
Fix: Database Encoding Breaks Search Results 1366 (HY000) Fix 'Incorrect string value' for emoji inserts in MySQL NULL Why MySQL index not used? Fix slow queries fast 0X00001A3F Fix SQL Server ERROR_TRANSACTIONMANAGER_NOT_ONLINE 0x1A3F

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.