The Anatomy of PHP-FPM Process Management
static, dynamic, and ondemand. Understanding how these policies allocate memory and spawn worker processes is critical for avoiding CPU context-switching overhead and Out-Of-Memory (OOM) killer events.
| PM Strategy | Best Use Case | Pros | Cons |
|---|---|---|---|
| Static | Dedicated high-RAM nodes | Zero allocation latency, highly predictable | Consumes steady memory even when idle |
| Dynamic | Shared or variable traffic | Adapts to load, conservative baseline memory | Process spawning overhead during traffic spikes |
| Ondemand | Low-traffic utility sites | Minimal idle footprint | High latency on initial cold requests |
static configuration combined with proper process limits typically yields the most consistent TTFB (Time to First Byte).
Calculating Realistic Worker Limits
pm.status shows that an average WordPress execution thread consumes 45MB of RAM at peak execution, the maximum static worker count is determined by the following formula:
Max Children Formula:Setting
Max Children = Allocated RAM / Average Process Memory
Max Children = 12,288 MB / 45 MB ≈ 273 workers
pm.max_children to 273 ensures the server will never trigger the kernel OOM killer under absolute full saturation.
Configuring Pool Parameters for Production
www.conf pool configuration designed for a high-performance production server using Unix domain sockets instead of TCP loopback to eliminate network stack overhead.
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = static
pm.max_children = 273
pm.max_requests = 1000
# Health check endpoint for load balancers
pm.status_path = /fpm-status
ping.path = /ping
# Resource limits
rlimit_files = 65535
rlimit_core = 0Mitigating Memory Leaks with pm.max_requests
pm.max_requests = 1000 ensures that every child process gracefully recycles itself after handling 1000 requests, completely eliminating gradual memory bloat without dropping incoming connections.
Monitoring and Diagnostic Tooling
location ~ ^/(fpm-status|fpm-ping)$ {
access_log off;
allow 127.0.0.1;
deny all;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}curl -s http://127.0.0.1/fpm-status?jsonactive processes, max active processes, and queue len. If queue len consistently climbs above zero, your pm.max_children ceiling is too restrictive, or underlying database bottlenecks are artificially inflating request execution time, holding workers hostage.