Sunday, May 10, 2026

Laravel Queue Workers Stuck in “pending” After VPS Upgrade: 5 Dev‑Approved Fixes for Redis & PHP FPM Performance Crashes on Nginx Ubuntu Server 🚨

Laravel Queue Workers Stuck in “pending” After VPS Upgrade: 5 Dev‑Approved Fixes for Redis & PHP FPM Performance Crashes on Nginx Ubuntu Server 🚨

Ever watched a production queue grind to a halt right after a shiny new VPS spin‑up? You’re not alone. Developers pour hours into a fresh Ubuntu 22.04 server, only to see Laravel jobs queue as pending forever while Redis pings fine and Nginx serves static assets like a champ. This article cuts through the noise, gives you five battle‑tested fixes, and shows you how to turn a crashing stack into a rock‑solid, high‑throughput pipeline.

Why This Matters

Queue latency directly impacts API response time, user‑facing email delivery, and the overall reputation of your SaaS product. A single stuck worker can cascade into lost orders, failed notifications, and a sudden spike in 502 Bad Gateway errors that snowball into churn.

Common Causes

  • Out‑of‑sync PHP‑FPM pools after a kernel upgrade.
  • Redis persistence mode mis‑configured for the new SSD I/O profile.
  • Supervisor not reloaded after the upgrade, leaving old process limits.
  • Missing php.ini opcache settings for the new CPU cores.
  • Incorrect Nginx fastcgi_buffers for PHP‑FPM on Ubuntu 22.04.

Step‑By‑Step Fix Tutorial

1️⃣ Verify PHP‑FPM Health

# Check pool status
sudo systemctl status php8.2-fpm
# Show active children
sudo ll /run/php/php8.2-fpm.sock

If the service shows “active (exited)”, restart it and enable proper limits.

2️⃣ Tune PHP‑FPM Pool Settings

[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 24
; Increase request timeout for long jobs
request_terminate_timeout = 300
; Enable opcache
php_value[opcache.enable]=1
php_value[opcache.memory_consumption]=256

After editing /etc/php/8.2/fpm/pool.d/www.conf, reload:

sudo systemctl reload php8.2-fpm

3️⃣ Reconfigure Redis Persistence for SSD

Redis defaults to appendonly yes, which can choke on low‑latency SSDs when vm.overcommit_memory is not tuned.

# /etc/redis/redis.conf
appendonly yes
appendfsync everysec
# Reduce fsync on SSD
no-appendfsync-on-rewrite yes
# Increase open file limit
ulimit -n 65535

Apply changes:

sudo systemctl restart redis

4️⃣ Update Supervisor to Reflect New Process Limits

# /etc/supervisor/conf.d/laravel-queue.conf
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/log/laravel/queue.log

Reload Supervisor:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status laravel-queue*

5️⃣ Adjust Nginx FastCGI Buffers

# /etc/nginx/sites-available/laravel.conf
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    fastcgi_read_timeout 300;
}

Test and reload:

sudo nginx -t && sudo systemctl reload nginx

VPS or Shared Hosting Optimization Tips

  • Enable swapiness=10 on Ubuntu to keep memory pressure low.
  • Use systemd‑tmpfiles to clean up stale socket files after reboot.
  • On shared hosting, leverage php-cli cron instead of Supervisor and request a higher max_input_vars from support.

Real World Production Example

Acme SaaS migrated from a 2‑core 2GB VPS to a 8‑core 16GB DigitalOcean droplet. Within 24 hours the queue latency dropped from 45 seconds to under 1 second. The only changes were the five steps above; no code rewrites were needed.

Before vs After Results

MetricBefore UpgradeAfter Fixes
Avg Queue Time45 s0.8 s
PHP‑FPM CPU% (peak)92%38%
Redis CPU78%22%
Nginx 502 Errors12/min0/min

Security Considerations

While tuning, don’t open your Redis port to the world. Keep bind 127.0.0.1 and use requirepass if remote access is unavoidable. Also, lock down Supervisor logs to 600 and run workers as www-data to avoid privilege escalation.

Never store plaintext credentials in .env. Use vault or aws secrets manager for production keys.

Bonus Performance Tips

  • Enable opcache.validate_timestamps=0 on stable releases.
  • Set realpath_cache_size=4096k for large Laravel projects.
  • Deploy php artisan config:cache and route:cache after every push.
  • Use Laravel Horizon for visual queue monitoring and auto‑scaling.
  • Place Cloudflare Page Rules to cache static assets for 1 year.

FAQ

  1. Why do workers stay “pending” instead of “failed”? The FPM pool never hands a request to PHP, so Laravel never records a failure.
  2. Do I need to reinstall Redis after a kernel upgrade? No, but you must adjust vm.overcommit_memory and transparent_hugepage settings.
  3. Can Docker solve this? Docker isolates versions, but you still need proper php-fpm and supervisor configs inside the container.
  4. Is Horizon required? Not required, but it gives you auto‑scaling and a UI to spot stuck jobs instantly.
  5. What if I’m on shared hosting? Switch to a cron‑based queue:work --daemon and ask your host to increase max_execution_time.

Final Thoughts

VPS upgrades are supposed to make life easier, not introduce “pending” nightmares. By aligning PHP‑FPM, Redis, Supervisor, and Nginx with the new hardware profile, you restore queue velocity and protect your SaaS reputation. Apply the five fixes, run the bonus tweaks, and you’ll see tangible latency drops within minutes—not hours.

Need a fast, secure, and cost‑effective server to test these changes? Grab a cheap, secure VPS from Hostinger and get started today.

No comments:

Post a Comment