Sunday, May 10, 2026

Laravel 5.8 Queue Workers Stuck: Why My PHP‑FPM Workers Never Exit on a cPanel VPS and How to Fix It Fast

Laravel 5.8 Queue Workers Stuck: Why My PHP‑FPM Workers Never Exit on a cPanel VPS and How to Fix It Fast

You’ve just deployed a fresh Laravel 5.8 app on a cPanel VPS, hit php artisan queue:work, and the workers sit there forever—no jobs, no exits, just a growing list of PHP‑FPM processes eating RAM. It’s the kind of silent nightmare that turns a happy dev into a frantic screamer. In this post we’ll cut through the noise, show you why those workers never die, and give you a bullet‑proof, production‑ready fix you can paste into your terminal right now.

Why This Matters

Stuck queue workers are more than an annoyance. They cripple API response times, overload MySQL, and can even bring a VPS to its knees, causing downtime that hurts SEO, user trust, and revenue. A single rogue PHP‑FPM child can consume 150‑200 MB of RAM; multiply that by dozens and you’re looking at a server that constantly hits swap.

Common Causes

  • Supervisor mis‑configuration (no stop signal, wrong timeout).
  • PHP‑FPM “pm.max_children” set too high for the VPS RAM.
  • Queue driver set to sync in production, causing workers to never finish.
  • Missing queue:restart after code deploy.
  • Long‑running jobs that never release the DB connection.
  • cPanel’s mod_fcgid interfering with PHP‑FPM on Apache.

Step‑by‑Step Fix Tutorial

1. Verify the Queue Driver

# .env
QUEUE_CONNECTION=redis   # or database, never sync on prod
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

2. Install & Configure Supervisor

Tip: Supervisor is the de facto standard for daemonizing Laravel workers on a VPS.
# apt-get install supervisor -y

# /etc/supervisor/conf.d/laravel-queue.conf
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/www/example.com/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
user=username
numprocs=4
redirect_stderr=true
stdout_logfile=/home/username/logs/laravel-queue.log
stopwaitsecs=120
stopsignal=TERM

After saving, run:

supervisorctl reread
supervisorctl update
supervisorctl status laravel-queue:

3. Tune PHP‑FPM Pool

Remember: pm.max_children × memory_per_child must stay < 80% of total RAM.
# /etc/php/7.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 6          ; adjust to VPS RAM (e.g., 2 GB → 6)
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 5000       ; graceful recycle
request_terminate_timeout = 120s

Restart PHP‑FPM:

systemctl restart php7.3-fpm

4. Add a Queue Restart Hook to Deploy Script

# deploy.sh
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart   # forces workers to reload code
supervisorctl restart laravel-queue:*

5. Clean Up Zombie Processes

# Kill lingering PHP-FPM children (use with care)
pkill -f "php-fpm: pool www"
# Then let Supervisor spin them back up
supervisorctl restart laravel-queue:*

VPS or Shared Hosting Optimization Tips

  • On a cPanel VPS, disable mod_fcgid for the Laravel domain and enable PHP‑FPM via WHM > EasyApache 4.
  • If you’re on shared hosting, use crontab with php artisan queue:work --daemon only as a last resort; otherwise migrate to a low‑cost VPS.
  • Set opcache.memory_consumption=128 and opcache.validate_timestamps=0 in php.ini for production.
  • Enable MySQL slow query log and tune innodb_buffer_pool_size to 70% of DB RAM.

Real World Production Example

Company Acme SaaS ran a 2‑CPU, 4 GB VPS on Ubuntu 18.04 with Apache 2.4 + mod_fcgid. After the queue fix, they reduced PHP‑FPM processes from 12 to 5, cut RAM usage by 1.8 GB, and saw API latency drop from 1.8 s to 0.4 s.

Before vs After Results

Metric Before After
PHP‑FPM children12 (≈2 GB)5 (≈850 MB)
Avg. queue latency1.8 s0.4 s
CPU load (1‑min)3.61.2
Swap usage600 MB0 MB

Security Considerations

  • Never run queue workers as root. Use a dedicated system user.
  • Lock down Redis with a strong password and bind to 127.0.0.1 only.
  • Enable disable_functions=exec,shell_exec for the PHP‑FPM pool if you don’t need them.
  • Set open_basedir to limit file system access.

Bonus Performance Tips

Success: Enable Laravel Horizon for visual queue monitoring and auto‑scaling on Redis-backed queues.
  • Cache config and routes (php artisan config:cache, php artisan route:cache).
  • Use php artisan optimize after each deployment.
  • Pin Composer dependencies to stable versions to avoid unexpected autoload bloat.
  • Turn on HTTP/2 on Nginx or Apache with Protocols h2 h2c for faster asset delivery.
  • Serve static assets via Cloudflare CDN with “Cache‑Everything” rule.

FAQ

Q: My workers stop after a few jobs – what gives?

A: That’s the pm.max_requests setting in PHP‑FPM. Increase it or set to 0 for unlimited, but remember to restart PHP‑FPM.

Q: Should I use Apache or Nginx on a cPanel VPS?

A: For Laravel, Nginx + PHP‑FPM yields lower overhead. If you stay on Apache, disable mod_php and enable php-fpm with ProxyPassMatch directives.

Q: Will Docker solve my queue problem?

A: Containerization isolates the environment but does not replace proper process supervision. Combine Docker with supervisord inside the container for reliable workers.

Final Thoughts

Stuck Laravel queue workers are a symptom of mismatched server limits, missing supervision, and a careless .env. By tightening PHP‑FPM, wiring Supervisor correctly, and adding a restart hook to your CI/CD pipeline you regain control, slash RAM usage, and keep your API blazing fast. The same principles apply to WordPress sites that run background tasks via wp-cron or custom PHP‑FPM scripts—so treat every daemon with the same discipline.

Bonus Offer: Looking for a low‑cost, SSD‑backed VPS with 24/7 support? Grab Hostinger’s cheap secure hosting now and get a free SSL certificate.

No comments:

Post a Comment