Wednesday, May 6, 2026

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

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.

INFO: The solutions below work for Laravel ≥9, PHP 8.1+, and cPanel/WHM environments that use either 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 supervisorctl restarts 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

  1. Over‑aggressive pm.max_children: Too many workers consume the entire RAM.
  2. Low memory_limit in php.ini: Laravel’s queue payload can easily exceed 128 MB when you use heavy jobs.
  3. cPanel “php‑fpm per user” isolation: Each account gets its own pool with default limits that don’t match a Laravel app.
  4. Mis‑configured supervisor.conf: Workers are spawned with “php artisan queue:work” without --memory=512 flag.
  5. 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
SUCCESS: Workers now stay alive, memory usage caps at ~480 MB per process, and the queue drains in half the previous time.

VPS or Shared Hosting Optimization Tips

  • Enable opcache.validate_timestamps=0 on production to eliminate file‑stat checks.
  • Use systemd limit directives (MemoryLimit=1G) to protect the host from runaway processes.
  • Place Redis on a separate Docker container with maxmemory 256mb and volatile-lru eviction.
  • 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

MetricBeforeAfter
CPU (avg)85%42%
RAM Used3.8 GB2.1 GB
Queue Lag9 min45 sec
Error Rate12%0.3%

Security Considerations

While increasing memory limits, don’t forget to harden the stack:

  • Run php-fpm under a dedicated system user with nosuid and noexec flags.
  • Set expose_php = Off in php.ini to hide version details.
  • Enable disable_functions = exec,shell_exec,system,passthru,proc_open for shared hosting.
  • Use Fail2Ban to block repeated php-fpm spawn failures.
  • Keep Composer dependencies up‑to‑date with composer audit.

Bonus Performance Tips

TIP: Add --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-redis client (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 16k and fastcgi_buffers 8 16k to reduce socket round‑trips.
  • Use opcache.preload to 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.

Looking for a cheap, secure VPS that ships with Ubuntu, Nginx, and Redis pre‑installed? Check out Hostinger’s VPS plans – perfect for Laravel and WordPress developers.

No comments:

Post a Comment