Laravel Queue Workers Zero‑Memory Crash on cPanel VPS: Why My FPM Config is Killing Performance and How to Fix It in 10 Minutes or Less
You’re staring at a “PHP process terminated unexpectedly – out of memory” line in storage/logs/laravel.log while your queue workers keep dying on a cheap cPanel VPS. Your production traffic spikes, your Redis queue backs up, and you’re left wondering why the same code runs fine on your local Mac. If you’ve ever felt that gut‑punch of frustration when a single config setting drags down an entire Laravel‑WordPress stack, keep reading. This guide shows you the exact PHP‑FPM tweak that stops the zero‑memory crash, plus a full 10‑minute fix checklist you can copy‑paste into any Ubuntu, AlmaLinux or CentOS VPS.
mod_fcgid or php-fpm under Apache or Nginx proxy.
Why This Matters
Queue workers are the backbone of real‑time notifications, e‑commerce order processing, and API throttling. When they silently exit because PHP‑FPM thinks the memory limit is reached, you lose:
- Customer trust – delayed emails or order confirmations.
- Server stability – a cascade of
supervisorctlrestarts overwhelms CPU. - Revenue – paid‑for VPS resources sit idle while the queue backs up.
Fixing the FPM configuration not only restores queue reliability but also improves overall WordPress performance on the same server, because both platforms share the same PHP pool.
Common Causes of Zero‑Memory Crashes
- Over‑aggressive
pm.max_children: Too many workers consume the entire RAM. - Low
memory_limitinphp.ini: Laravel’s queue payload can easily exceed 128 MB when you use heavy jobs. - cPanel “php‑fpm per user” isolation: Each account gets its own pool with default limits that don’t match a Laravel app.
- Mis‑configured
supervisor.conf: Workers are spawned with “php artisan queue:work” without--memory=512flag. - Redis overflow: When Redis fills up, Laravel keeps the job in memory, pushing the process over its limit.
Step‑By‑Step Fix Tutorial
1. Locate the Active PHP‑FPM Pool
cPanel stores pools in /usr/local/php*/etc/php-fpm.d. Identify the pool used by your domain:
grep -i listen /usr/local/php*/etc/php-fpm.d/*.conf
# Example output:
# /usr/local/php81/etc/php-fpm.d/example.com.conf:listen = /opt/cpanel/ea-php81/root/usr/var/run/php-fpm/example.com.sock
2. Adjust pm.max_children and pm.max_requests
Open the pool file and set realistic values based on your VPS RAM (e.g., 2 GB):
# /usr/local/php81/etc/php-fpm.d/example.com.conf
pm = dynamic
pm.max_children = 8 # 8 × 256 MB = 2 GB
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 5000
3. Raise the PHP memory_limit
Edit the global php.ini or the pool‑specific php_value[memory_limit]:
# /usr/local/php81/etc/php.ini
memory_limit = 512M
# or inside the pool
php_value[memory_limit] = 512M
4. Add a Supervisor Config with Proper Memory Flag
Place this file in /etc/supervisord.d/laravel-queue.conf (or /etc/supervisor/conf.d on Ubuntu):
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/example.com/artisan queue:work redis --sleep=3 --tries=3 --memory=512
autostart=true
autorestart=true
user=username
numprocs=4
redirect_stderr=true
stdout_logfile=/home/username/example.com/storage/logs/worker.log
stopwaitsecs=3600
5. Restart Services
# Restart PHP‑FPM pool
/usr/local/cpanel/scripts/restartsrv_php_fpm
# Reload Supervisor
supervisorctl reread && supervisorctl update
# Verify worker status
supervisorctl status laravel-queue
VPS or Shared Hosting Optimization Tips
- Enable
opcache.validate_timestamps=0on production to eliminate file‑stat checks. - Use
systemdlimit directives (MemoryLimit=1G) to protect the host from runaway processes. - Place Redis on a separate Docker container with
maxmemory 256mbandvolatile-lrueviction. - Configure Cloudflare page rules to cache static assets from the WordPress front‑end, reducing PHP hits.
- When on shared cPanel, request higher “PHP‑FPM per user” limits from your host or migrate to a lightweight VPS.
Real World Production Example
Acme SaaS runs a Laravel API on a 2 vCPU, 4 GB RAM Ubuntu 22.04 VPS behind Nginx. Before the fix:
- Queue worker memory spiked to 1 GB → OOM kill.
- Redis hit 95% memory, causing
READONLY You can't write to a read‑only replica. - Customer order emails delayed by 12‑minutes on average.
After applying the steps above:
- Average worker memory: 420 MB.
- Redis peak: 70% with
maxmemory-policy allkeys-lru. - Email latency dropped to < 30 seconds.
Before vs After Results
| Metric | Before | After |
|---|---|---|
| CPU (avg) | 85% | 42% |
| RAM Used | 3.8 GB | 2.1 GB |
| Queue Lag | 9 min | 45 sec |
| Error Rate | 12% | 0.3% |
Security Considerations
While increasing memory limits, don’t forget to harden the stack:
- Run
php-fpmunder a dedicated system user withnosuidandnoexecflags. - Set
expose_php = Offinphp.inito hide version details. - Enable
disable_functions = exec,shell_exec,system,passthru,proc_openfor shared hosting. - Use Fail2Ban to block repeated
php-fpmspawn failures. - Keep Composer dependencies up‑to‑date with
composer audit.
Bonus Performance Tips
--daemon to queue:work only when you have a stable FPM pool. In noisy cPanel environments, the non‑daemon mode reduces memory fragmentation.
- Enable
async-redisclient (predis → phpredis) for ~30% lower latency. - Cache Laravel config and routes:
php artisan config:cache && php artisan route:cache. - Offload static WordPress assets to Cloudflare’s CDN with
Cache‑Level: Cache Everything. - Set Nginx
fastcgi_buffer_size 16kandfastcgi_buffers 8 16kto reduce socket round‑trips. - Use
opcache.preloadto preload Composer autoload files.
FAQ
Q1: Do I need to restart cPanel after editing PHP‑FPM pools?
A: Yes. Use /usr/local/cpanel/scripts/restartsrv_php_fpm or the WHM “Restart Services → PHP -FPM” button.
Q2: My VPS runs Apache only – can I still apply these settings?
A: Absolutely. Apache with mod_fcgid respects the same php.ini limits. Just adjust FcgidMaxProcesses accordingly.
Q3: Will increasing memory_limit affect other sites on the same server?
A: On a shared cPanel account each domain has its own pool, so the change is isolated. On a single‑user VPS it applies globally, so monitor total RAM usage.
Q4: How do I know the optimal pm.max_children value?
A: Use free -m and top while a worker is busy. Divide total RAM (minus OS overhead) by the average worker RSS.
Q5: Can Docker replace Supervisor for queue workers?
A: Yes, but you still need to respect PHP memory limits inside the container. A docker‑compose.yml with mem_limit: 1g works well.
Final Thoughts
Zero‑memory crashes on cPanel VPS are rarely a Laravel bug; they’re a mis‑aligned PHP‑FPM configuration. By tuning pm.max_children, bumping memory_limit, and managing workers with Supervisor, you reclaim stability in under ten minutes. The side effect? Your WordPress front‑end becomes snappier, Redis stays healthy, and you finally have headroom to add new features without fearing OOM kills.
No comments:
Post a Comment