Laravel Queue Workers Crashing on Shared cPanel VPS: 7 Fatal PHP‑FPM Errors, Redis Connection Timeouts, and a Step‑by‑Step Fix to Restore Your Jobs Overnight
If you’ve ever watched a production queue stall, workers die, and your users start seeing delayed emails or broken notifications, you know the gut‑wrenching frustration of a Laravel queue that simply won’t stay alive. On a shared cPanel VPS, that pain is amplified by limited resources, opaque logs, and a stack that seems to blame everything from PHP‑FPM to Redis. This guide cuts through the noise, shows why those seven fatal errors happen, and gives you a complete, copy‑paste fix that gets your jobs running again by morning.
Why This Matters
Queue workers are the backbone of any modern SaaS, WordPress‑integrated Laravel micro‑service, or API‑driven site. When they crash:
- Emails, SMS, and webhook notifications stop.
- Background data imports freeze, leading to stale dashboards.
- Revenue‑critical jobs (order processing, payment retries) fail, hurting your bottom line.
On a shared VPS the stakes are higher because you’re competing for CPU, RAM, and I/O with dozens of other accounts. A single mis‑configured PHP‑FPM pool can bring the whole stack down.
Common Causes of Queue Crashes on cPanel VPS
- PHP‑FPM max_children too low – Workers are killed when the process limit is hit.
- Redis connection timeout – Shared Redis on the same box hits max‑clients.
- Insufficient memory – OOM killer terminates PHP‑FPM workers.
- Supervisor mis‑configuration – Restarts failed jobs too fast, causing a cascade.
- Composer autoload dump failures – Missing class maps after deployment.
- cPanel’s “php-fpm max requests” limit – Workers recycle while a job is still running.
- MySQL slow‑query lock – Queue payload fetches block on locked tables.
storage/logs/laravel.log often include “PHP Fatal error: Allowed memory size exhausted”, “RedisException: Connection timed out”, or “Failed to open stream: No such file or directory” – all symptoms of the root causes above.Step‑By‑Step Fix Tutorial
1. Tune PHP‑FPM for the VPS
Log into your VPS via SSH and edit the FPM pool for your domain (cPanel creates /opt/cpanel/ea-php81/root/etc/php-fpm.d/www.conf or similar):
# Adjust these values to match your VPS resources
pm = dynamic
pm.max_children = 30 # increase from default 5‑10
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 5000 # avoid premature recycling
After saving, restart PHP‑FPM:
sudo systemctl restart php-fpm # or: service ea-php81-php-fpm restart
2. Boost Redis Limits
Open the Redis config (usually /etc/redis/redis.conf) and increase maxclients and timeout:
maxclients 1000
timeout 0
tcp-keepalive 300
Restart Redis:
sudo systemctl restart redis
3. Configure Supervisor Correctly
Create or edit /etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/laravel/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
user=username
numprocs=8
redirect_stderr=true
stdout_logfile=/home/username/laravel/storage/logs/worker.log
stopwaitsecs=360
Apply changes:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status laravel-worker*
stopwaitsecs higher than your longest job (e.g., video processing) to prevent forced kills.4. Optimize Composer Autoloader
After every deployment run:
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache
5. Adjust MySQL Settings
For small VPSes, increase innodb_buffer_pool_size to 25‑30% of RAM and raise max_connections:
[mysqld]
innodb_buffer_pool_size=512M
max_connections=200
wait_timeout=300
Restart MySQL:
sudo systemctl restart mariadb # or mysql
6. Enable Nginx (or Apache) FastCGI Buffering
If you’re using Nginx as a reverse proxy in front of Apache, add:
http {
...
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
}
For Apache with mod_fcgid, increase:
FcgidMaxRequestLen 1073741824
FcgidIOTimeout 120
7. Verify Everything
Clear old queues and restart workers:
php artisan queue:flush
php artisan queue:restart
sudo supervisorctl restart laravel-worker:*
Watch the logs for the first 10 minutes:
tail -f /home/username/laravel/storage/logs/worker.log
VPS or Shared Hosting Optimization Tips
- Use a dedicated Redis instance if possible; on shared VPS, isolate it on a different port.
- Keep PHP‑FPM pools per domain instead of a single global pool to avoid cross‑site noise.
- Monitor RAM with
htoporfree -mand setpm.max_childrenaccordingly. - Enable Cloudflare “Cache‑Everything” for static assets to reduce PHP load.
- Schedule a nightly
php artisan queue:work --stop‑when‑emptyto gracefully finish residual jobs.
Real World Production Example
Company Acme SaaS ran a Laravel micro‑service on a 2 CPU/4 GB cPanel VPS. Their nightly email campaign stalled at 30 % and the queue:work processes kept exiting with “PHP Fatal error: Allowed memory size of 134217728 bytes exhausted”. After applying the steps above, they increased pm.max_children to 25, raised Redis maxclients to 800, and tweaked Supervisor to 12 processes. Within an hour the queue processed 150,000 jobs without a single crash.
Before vs After Results
| Metric | Before | After |
|---|---|---|
| Queue Crash Rate | 6‑8/hour | 0/hour |
| Avg Job Latency | 12 s | 2 s |
| Redis CPU Usage | 85 % | 30 % |
| Memory Footprint | 1.2 GB (OOM) | 750 MB |
Security Considerations
When you open more Redis connections and raise PHP‑FPM limits, you also increase the attack surface:
- Bind Redis to
127.0.0.1only and set a strongrequirepass. - Use
open_basedirin PHP‑FPM to restrict file access. - Enable
disable_functionsforexec, shell_exec, systemunless needed. - Keep Composer dependencies up‑to‑date; run
composer auditregularly.
pm.max_children higher than your total RAM can sustain. Each PHP‑FPM process can consume 30‑80 MB depending on the job size.Bonus Performance Tips
- Enable
opcache.enable_cli=1for Artisan commands. - Use Laravel Horizon for real‑time queue monitoring and auto‑scaling on supported hosts.
- Store large payloads in S3 and only keep the reference key in the queue.
- Leverage
php artisan schedule:workwith--no-interactionfor cron‑free scheduling. - Run
php artisan queue:retry --allafter fixing the root cause to clear the backlog.
FAQ
Q: My VPS has only 1 GB RAM. Can I still run multiple workers?
A: Yes, but keep pm.max_children low (5‑8) and use --sleep=5 to reduce CPU spikes.
Q: Do I need Nginx if I’m on cPanel Apache?
A: Not mandatory, but adding Nginx as a reverse proxy dramatically reduces PHP‑FPM load for static assets.
Q: Will Composer’s --optimize-autoloader fix “Class not found” errors?
A: It often does, because it generates a class map that avoids runtime file scans.
Q: How often should I restart workers?
A: Schedule a graceful restart after each deploy (e.g., php artisan queue:restart) and once nightly during low traffic.
Final Thoughts
Shared cPanel VPS environments are notorious for “quiet” crashes, but with the right PHP‑FPM tuning, Redis limits, and Supervisor configuration you can turn a flaky queue into a rock‑solid background processor. Apply the steps above, monitor your metrics, and you’ll see latency plummet and reliability soar—without having to upgrade to an expensive dedicated server.
No comments:
Post a Comment