Laravel Queue Workers Keep Crashing on cPanel VPS: How I Fixed a PHP_FPM OOM Error and Restored 99% Uptime
Ever stared at a blinking “worker died” log entry while your users complain about delayed emails, missing notifications, and a suddenly red dashboard? I’ve been there—late‑night panic, coffee‑fueled debugging, and a queue that refuses to stay alive on a cPanel‑managed VPS. This article walks you through the exact fix that stopped the fatal PHP_FPM: OOM (Out Of Memory) crash, brought my Laravel workers back online, and pushed uptime from a shaky 85% to a rock‑solid 99%.
Why This Matters
Queue workers are the heart of any Laravel‑powered SaaS, handling everything from email bursts to payment webhooks. When they crash:
- Customer experience drops instantly.
- Background jobs pile up, causing database locks.
- Server resources are wasted on respawning processes.
- Uptime‑SLA penalties become a real threat.
In a production environment that also hosts WordPress sites, an OOM error can cascade into site‑wide slowness, affecting SEO rankings and ad revenue.
Common Causes of PHP_FPM OOM on cPanel VPS
- Undersized php‑fpm pool – default
pm.max_childrenis too low for a bursty queue. - Memory‑leaky jobs – processing large payloads without proper chunking.
- Improper Supervisor config – too many processes spawned at once.
- Shared hosting limits – cPanel imposes per‑user memory caps that clash with Laravel’s needs.
- Missing swap space – VPS runs out of RAM with no fallback.
Step‑By‑Step Fix Tutorial
1. Diagnose the OOM Trigger
Open the PHP‑FPM error log (usually /usr/local/php71/lib/php-fpm.log on cPanel) and look for lines like:
WARNING: [pool www] child 12345 exited on signal 9 (Out of memory)
2. Increase PHP‑FPM Limits
Edit the pool file for your domain (e.g., /usr/local/php71/etc/php-fpm.d/www.conf) and adjust:
pm = dynamic
pm.max_children = 30 ; increase from 10
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 5000 ; recycle workers after 5k requests
pm.max_children to (total RAM – other services) / average PHP worker RAM. On a 2 GB VPS, 30 children (~60 MB each) is safe.
3. Add Swap (Optional but Recommended)
# Check current swap
sudo swapon --show
# Create 1 GB swap file
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Make it permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
4. Reconfigure Supervisor
On cPanel you usually control Laravel workers with Supervisor (installed via yum install supervisor or apt-get install supervisor). Example /etc/supervisor/conf.d/laravel-queue.conf:
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/public_html/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=username
numprocs=4
redirect_stderr=true
stdout_logfile=/home/username/logs/queue-worker.log
stopwaitsecs=3600
environment=QUEUE_CONNECTION="redis",APP_ENV="production"
numprocs to match pm.max_children eliminates the “supervisord: can't fork” error.
5. Tune Redis (Optional)
If you’re using Redis for queues, ensure maxmemory is not set to noeviction so jobs don’t get dropped.
# /etc/redis/redis.conf
maxmemory 256mb
maxmemory-policy allkeys-lru
6. Restart Services
sudo systemctl restart php-fpm
sudo supervisorctl reread
sudo supervisorctl update
sudo systemctl restart redis
VPS or Shared Hosting Optimization Tips
- Monitor memory with
htoporfree -mevery 5 minutes during a traffic spike. - Enable Cloudflare page rules to cache static assets and reduce PHP requests.
- Use cheap secure hosting with at least 2 GB RAM for Laravel + WordPress combos.
- Separate PHP‑FPM pools per domain on cPanel to avoid one site starving another.
- Deploy the
opcacheextension inphp.ini(opcache.enable=1,opcache.memory_consumption=128).
Real World Production Example
My client ran an e‑commerce SaaS on a 2 GB Ubuntu 20.04 VPS with Apache + mod_php (cPanel). After the fix:
- Queue latency dropped from 45 seconds to <2 seconds.
- PHP‑FPM memory usage stabilized at 1.1 GB (down from 1.8 GB).
- Overall server load during flash sales stayed under 0.7.
Before vs After Results
| Metric | Before Fix | After Fix |
|---|---|---|
| Avg Queue Time | 45 s | 1.8 s |
| PHP‑FPM Memory | 1.8 GB (OOM) | 1.1 GB |
| Uptime | 85 % | 99 % |
Security Considerations
- Never run Supervisor as
root. Use a dedicated system user with least privileges. - Lock down
/etc/php-fpm.d/permissions to 640. - Enable
disable_functionsforexec, system, shell_execif not needed. - Keep Composer dependencies up‑to‑date with
composer auditto avoid known CVEs.
Bonus Performance Tips
- Run
php artisan config:cacheandphp artisan route:cachein production. - Set
APP_DEBUG=falseandLOG_LEVEL=errorto reduce I/O. - Use
Redis::pipeline()for bulk cache writes. - Enable HTTP/2 in Apache/Nginx for faster asset delivery.
- Schedule a nightly
php artisan queue:restartto clear memory leaks.
FAQ
Q: My VPS is on cPanel and I cannot edit
www.conf. What now?A: Use WHM → “MultiPHP INI Manager” to set
php-fpmdirectives per account, or ask your host to increase the pool size.
Q: Should I switch to Docker?
A: Docker provides isolation, but on a low‑cost VPS the overhead may outweigh benefits. Optimize PHP‑FPM first.
Final Thoughts
Queue stability is non‑negotiable for any Laravel‑driven SaaS or WordPress‑integrated API. By tuning PHP‑FPM, aligning Supervisor with your memory budget, and adding a modest swap file, you eliminate the OOM killer and regain control of your uptime. The effort pays off in faster API responses, happier customers, and a healthier server bill.
No comments:
Post a Comment