Running too few PHP-FPM worker processes causes request queuing, 502 errors, and the pm.max_children warning in the FPM log. This guide shows how to measure per-process memory and calculate the right values for your server.
Prerequisites
- Nginx + PHP-FPM running
- Access to
/etc/php/fpm/pool.d/www.conf (Debian) or /etc/php-fpm.d/www.conf (CentOS)
- A stable workload (results fluctuate on shared hosting with varied codebases)
Identify the problem
These warnings in the PHP-FPM log indicate insufficient workers:
[pool www] server reached pm.max_children setting (35), consider raising it
[pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
Measure per-process memory
Option 1 — list all processes and their RSS:
ps -ylC php-fpm --sort:rss
The RSS column is non-swapped physical memory in kilobytes. Example output:
S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
S 0 24439 1 0 80 0 6364 57236 - ? 00:00:00 php-fpm
S 33 24701 24439 2 80 0 61588 63335 - ? 00:04:07 php-fpm
S 33 25319 24439 2 80 0 61620 63314 - ? 00:02:35 php-fpm
Here each worker uses approximately 60 MB.
Option 2 — compute the average directly:
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s
", sum/NR/1024,"Mb") }'
Calculate pm.max_children
pm.max_children = (RAM available to PHP-FPM in MB) / (avg worker size in MB)
Example: 4 GB server, MariaDB using ~1 GB, 0.5 GB headroom for OS:
(4096 - 1024 - 512) MB / 60 MB ≈ 42 → set pm.max_children = 40
Steps — apply the settings
Edit the pool config:
pm = dynamic
pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25
pm.max_requests = 500
Restart PHP-FPM:
sudo systemctl restart php-fpm
Verify
sudo systemctl status php-fpm
tail -f /var/log/php-fpm/error.log
Watch the log for a few minutes under normal traffic; the pm.max_children warning should stop appearing.
Notes
- Never allocate 100% of RAM to PHP-FPM — always reserve memory for the OS, database, and other services.
- For heavy frameworks (e.g. Magento 2), use at least 128 MB per worker in your calculation.
pm.max_requests = 500 recycles workers to prevent slow memory leaks.