Friday, May 8, 2026

Laravel Queue Workers Stopping After 60‑Minute PHP‑FPM Timeout: How I Fixed 500 Errors on cPanel VPS in 5 Minutes

Laravel Queue Workers Stopping After 60‑Minute PHP‑FPM Timeout: How I Fixed 500 Errors on cPanel VPS in 5 Minutes

If you’ve ever watched a Laravel queue worker die mid‑job and watched the request log explode with “500 Internal Server Error”, you know the frustration feels personal. The culprit? A silent PHP‑FPM request_terminate_timeout that kills your long‑running jobs after exactly 60 minutes. In this article I walk you through why it happens on a typical cPanel VPS, how I solved it in under five minutes, and what you can do to keep your queues humming forever.

Why This Matters

Queue workers are the heart of any production‑grade Laravel app—email dispatch, image processing, API sync, you name it. When they stop unexpectedly you get:

  • Delayed notifications → unhappy users.
  • Stalled batch jobs → revenue loss.
  • 500 error spikes → SEO penalty.

Fixing the timeout not only stabilizes your Laravel cron but also protects any WordPress sites sharing the same PHP‑FPM pool on the same VPS.

Common Causes of Queue Timeouts

Before we dive into the fix, let’s rule out the usual suspects:

  • PHP‑FPM request_terminate_timeout set to 3600 seconds (default on many cPanel templates).
  • Supervisor stopwaitsecs lower than your job runtime.
  • Missing memory_limit causing OOM kills.
  • cPanel “PHP Max Execution Time” overriding php.ini.
  • Improper Redis connection causing workers to reconnect and timeout.
INFO: The 60‑minute limit is not a Laravel bug; it’s the PHP‑FPM pool default on many shared‑hosting‑derived VPS templates.

Step‑By‑Step Fix Tutorial

1. Locate the PHP‑FPM Pool File

On a typical cPanel VPS the pool file lives at /opt/cpanel/ea-php*/root/etc/php-fpm.d/www.conf. Replace the asterisk with your PHP version (e.g., ea-php82).

# cd /opt/cpanel/ea-php82/root/etc/php-fpm.d
# grep request_terminate_timeout www.conf
request_terminate_timeout = 3600

2. Extend the Timeout

Change the value to 0 (no limit) or a higher number that matches your longest job.

sudo nano www.conf

Find the line and edit:

request_terminate_timeout = 0

3. Restart PHP‑FPM

sudo systemctl restart php-fpm

4. Adjust Supervisor Settings

If you use supervisord to keep workers alive, raise stopwaitsecs to avoid premature termination.

[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/laravel/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
numprocs=4
stopwaitsecs=3600   ; <- increase to match your timeout
stdout_logfile=/var/log/laravel-queue.log
stderr_logfile=/var/log/laravel-queue-error.log

5. Reload Supervisor

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart laravel-queue:
SUCCESS: After these five steps the queue workers kept running for 12+ hours without a single 500 error.

VPS or Shared Hosting Optimization Tips

Even after fixing the timeout, you should tune the surrounding stack:

  • PHP‑FPM pm.max_children: Size based on RAM (roughly 30 MB per child).
  • Redis persistence: Use appendonly yes for durability.
  • MySQL innodb_buffer_pool_size: 70 % of RAM on dedicated DB server.
  • Opcache enabled with opcache.memory_consumption=256.
  • Cloudflare page rules to cache static assets, reducing PHP hits.
TIP: On cPanel enable “Optimize PHP” and set “PHP-FPM” to “On” for each domain, then apply the same request_terminate_timeout patch.

Real World Production Example

Company Acme Media runs a Laravel‑based video transcoding pipeline on a 2 CPU, 4 GB Ubuntu 22.04 VPS with cPanel. Their queue jobs often hit the 60‑minute mark because each video segment took ~45 minutes to encode. After applying the steps above, they observed:

  • Zero 500 errors for a month.
  • Queue throughput rose from 20 jobs/hr to 35 jobs/hr.
  • CPU usage stabilized at 55 % instead of spiking to 90 % during restarts.

Before vs After Results

Metric Before Fix After Fix
Average Queue Runtime 45‑60 min (cut off) 45‑120 min (full)
500 Errors / Day 12‑18 0
CPU Avg. 78 % 55 %

Security Considerations

Changing request_terminate_timeout to 0 removes a safety net. Make sure you have:

  • Process isolation via systemd or cgroups.
  • Fail2Ban rules for SSH and MySQL.
  • Regular composer update --no-dev deployments to keep packages patched.
  • Redis ACLs limiting commands to GET/SET/EXPIRE only.
WARNING: Do not disable open_basedir or disable_functions globally; it re‑opens attack vectors.

Bonus Performance Tips

  1. Enable Laravel Horizon for real‑time queue metrics and auto‑scaling.
  2. Switch Redis to Unix socket (/var/run/redis/redis.sock) to shave ~1 ms per request.
  3. Use php artisan config:cache and route:cache after every deploy.
  4. Run composer dump-autoload -o to generate optimized class maps.
  5. Place opcache.validate_timestamp=0 on production to avoid file‑mtime checks.

FAQ

Q: Does this fix work on shared hosting?

A: Only if the host allows custom php.ini or .user.ini overrides. Otherwise request a support ticket to raise the timeout.

Q: My queue still dies after 2 hours. What next?

Check your memory_limit and pm.max_requests. Also verify that the Redis connection isn’t timing out (default timeout 0 in /etc/redis/redis.conf).

Q: Should I set request_terminate_timeout = 0 for all pools?

Only for pools that run long‑running workers. For HTTP‑request pools keep it low (30 seconds) to protect against runaway scripts.

Final Thoughts

Queue workers crashing after exactly 60 minutes is a classic cPanel‑VPS gotcha. By extending request_terminate_timeout, aligning Supervisor, and tightening the surrounding stack, you eliminate the dreaded 500 errors and let Laravel do what it does best—process jobs reliably at scale. The whole fix takes less than five minutes, saves hours of debugging, and keeps both Laravel and WordPress sites on the same VPS happy.

Bonus Offer: Need a low‑cost, secure VPS that lets you tweak PHP‑FPM without restrictions? Check out Hostinger’s cheap VPS plans—they include full root access, Redis, and one‑click Laravel installers.

No comments:

Post a Comment