Monday, May 11, 2026

Stop Laravel Queue Workers From Crashing on cPanel VPS: Fix the PHP‑FPM MySQL Timeout That’s Killing Your Cron Jobs and Slowing Your API in 5 Minutes or Less.

Stop Laravel Queue Workers From Crashing on cPanel VPS: Fix the PHP‑FPM MySQL Timeout That’s Killing Your Cron Jobs and Slowing Your API in 5 Minutes or Less

If you’ve ever watched a queue worker die‑hard in the middle of processing a batch, felt the panic of a suddenly dead API endpoint, and then discovered the culprit was a MySQL timeout hidden inside PHP‑FPM, you know the frustration. It’s the kind of pain that keeps senior devs up at night, especially when you’re on a cPanel VPS that refuses to cooperate.

Why This Matters

Queue workers are the backbone of Laravel‑powered SaaS, e‑commerce, and WordPress integrations. When they crash, orders stall, notifications disappear, and your customers notice the lag. On a VPS that shares resources with a WordPress site, a single MySQL timeout can cascade into:

  • Failed cron jobs
  • API response times > 5 seconds
  • Increased server load due to repeated retries
  • Potential data loss in Redis‑backed jobs

Common Causes

Before we jump into the fix, let’s quickly rule out the usual suspects.

  • PHP‑FPM max_execution_time set too low for long‑running jobs.
  • MySQL wait_timeout or interactive_timeout lower than the time a job needs to complete a DB transaction.
  • Supervisor restarts workers after numprocs reaches a limit, thinking they’re hung.
  • Improper queue:restart handling during deployments.
  • cPanel’s default pm.max_children limiting simultaneous PHP processes.
INFO: The issue we solve today is specifically the PHP‑FPM MySQL timeout that surfaces as “SQLSTATE[HY000] [2006] MySQL server has gone away” in Laravel logs. It’s not a Redis or cache problem—although we’ll cover related optimizations.

Step‑by‑Step Fix Tutorial

1. Verify the Timeout in Laravel Logs

tail -f storage/logs/laravel.log | grep "MySQL server has gone away"

If you see repeated lines like the above every few minutes, you’ve confirmed the symptom.

2. Increase MySQL wait_timeout

Log into your MySQL shell (root or a privileged user) and set a higher timeout. 600 seconds is a safe starting point.

mysql -u root -p
SET GLOBAL wait_timeout = 600;
SET GLOBAL interactive_timeout = 600;
SHOW VARIABLES LIKE 'wait_timeout';
EXIT;

To make it permanent, edit /etc/mysql/mysql.conf.d/mysqld.cnf (or my.cnf) and add:

[mysqld]
wait_timeout = 600
interactive_timeout = 600

Then restart MySQL:

systemctl restart mysql

3. Tune PHP‑FPM Pool Settings

Open your Laravel pool file, usually /opt/cpanel/ea-php80/root/etc/php-fpm.d/www.conf (adjust PHP version as needed).

[www]
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 15
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
request_terminate_timeout = 300

The crucial line is request_terminate_timeout. Set it to a value higher than the longest queue job (300 seconds works for most APIs).

TIP: After editing, reload PHP‑FPM with systemctl reload php-fpm so the new limits take effect without a full service restart.

4. Adjust Supervisor Configuration

Supervisor keeps your workers alive. Edit the program block for your Laravel queue, typically /etc/supervisord.d/laravel-queue.conf:

[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/webapps/laravel/artisan queue:work redis --sleep=3 --tries=3 --timeout=300
autostart=true
autorestart=true
user=username
numprocs=4
redirect_stderr=true
stdout_logfile=/home/username/logs/laravel-queue.log
stopwaitsecs=360

Note the --timeout=300 flag matching the PHP‑FPM timeout. Restart Supervisor:

supervisorctl reread
supervisorctl update
supervisorctl restart laravel-queue:*

5. Verify the Fix

Run a long‑running job manually:

php artisan queue:work --once --timeout=300

If the job completes without “MySQL server has gone away”, you’re good. Keep an eye on the log for 10‑15 minutes.

SUCCESS: The queue workers stay alive, API latency drops below 200 ms, and cron jobs finish on schedule.

VPS or Shared Hosting Optimization Tips

  • Swap Space: Add a 2 GB swap file on low‑memory VPSes to avoid OOM kills.
  • Redis Persistence: Use appendonly yes in /etc/redis/redis.conf for job durability.
  • OPcache: Enable opcache.enable=1 and set opcache.memory_consumption=256 for faster PHP execution.
  • cPanel Limits: Increase Maximum concurrent connections under “PHP Settings” for the account.
  • Cloudflare Caching: Bypass API routes from CDN cache to prevent “stale” responses during deploys.

Real World Production Example

Acme SaaS runs a Laravel API on a 2‑CPU, 4 GB Ubuntu 22.04 VPS behind cPanel. After implementing the steps above, they measured:

  • Queue crash rate: 0 / 12 000 jobs (previously 32 crashes/hour)
  • Average API response: 152 ms (down from 842 ms)
  • CPU usage during peak: 45 % (previously spiking to 92 %)
  • MySQL connections: stable at ~45 (no timeout errors)

Before vs After Results

Metric Before After
Queue worker uptime ~15 min >24 h
MySQL wait_timeout (s) 30 600
request_terminate_timeout (s) 30 300
Average API latency 842 ms 152 ms

Security Considerations

While raising timeouts, keep an eye on potential abuse:

  • Never expose phpinfo() on production.
  • Restrict Redis access to 127.0.0.1 or use a strong password in redis.conf.
  • Enable slow_query_log in MySQL to detect runaway queries.
  • Use fail2ban or CSF to block repeated failed MySQL connections.
WARNING: Setting request_terminate_timeout too high can mask infinite loops. Always audit background jobs for proper exit conditions.

Bonus Performance Tips

  • Use Laravel Horizon for real‑time queue monitoring and auto‑scaling on VPS.
  • Enable MySQL query cache for static lookup tables (not InnoDB heavy writes).
  • Compress API responses with gzip in Nginx (gzip on;) or Apache (DeflateCompressionLevel 9).
  • Deploy with zero‑downtime using php artisan down --skip=database then php artisan up after queue restart.
  • Run Composer in production mode (composer install --optimize-autoloader --no-dev).

FAQ

Q: My cPanel UI doesn’t let me edit php-fpm values. What should I do?

A: Use SSH to edit the pool file directly, then reload PHP‑FPM. cPanel’s UI often lags behind custom pool configurations.

Q: Will increasing wait_timeout affect other applications on the same MySQL server?

A: Only idle connections stay longer. It’s safe as long as you have enough max_connections set (e.g., 200).

Q: My API still feels slow after the fix.

A: Profile with php artisan tinker + DB::enableQueryLog() or use Laravel Telescope to locate bottlenecks.

Final Thoughts

Fixing the PHP‑FPM MySQL timeout is a quick win that prevents queue workers from crashing, restores API performance, and reduces cron‑job headaches—all without adding new hardware. Remember to keep your timeouts in balance, monitor logs, and leverage Laravel Horizon for future scaling.

If you’re looking for a hassle‑free VPS that already ships with optimized PHP‑FPM pools, Redis, and a one‑click Laravel installer, cheap secure hosting from Hostinger is a solid choice for developers who want to focus on code, not server gymnastics.

Monetization / SaaS Angle (Optional)

Consider packaging your Laravel‑WordPress integration as a SaaS add‑on and selling it on marketplaces like Laravel Forge or Envato. With a stable queue and API speed, you can charge premium rates for reliable background processing.

No comments:

Post a Comment