pm.max_children caps concurrent PHP-FPM workers. When all are busy, incoming requests wait in a queue; a client can see 502, 503 or 504 depending on the proxy and failure mode. Confirm pool saturation in status and logs before sizing the limit from available memory and downstream capacity.

“PHP-FPM 502” describes a gateway symptom, not a status sent directly by FPM. nginx talks to FPM over FastCGI; it may return 502 for a broken or invalid upstream response and 504 when waiting times out. Locate the emitter with the 5xx guide. Pool settings are specified in the PHP-FPM configuration manual.
Inspect the queue and worker cap
| Signal | Where | Meaning |
|---|---|---|
max children reached | FPM log or status page | Pool hit its limit at least once |
listen queue | FPM status page | Requests waiting for a worker now |
active processes | FPM status page | Busy workers at sampling time |
upstream timed out | nginx error.log | Find the delayed phase and cause |
The FPM status page exposes listen queue, max listen queue and max children reached. Keep it internal: full status can reveal request URLs. Under pm = dynamic, check start and spare-server settings too. Under ondemand, account for process startup and idle timeout. A slow database may occupy workers even when the configured maximum looks generous.

Size the pool from available memory
A simplified upper bound is floor(memory_for_FPM / memory_per_worker). If 2 GiB remain after reserving memory for the OS, nginx and database, and a busy worker consumes about 100 MiB, the initial estimate is 20 workers. This is a teaching example, not a measurement of enterno.io or a ready production limit. Memory changes across requests; shared pages can be double-counted in RSS. Sample PSS or USS under real load rather than a single idle RSS.
ps -eo pid,rss,cmd | grep '[p]hp-fpm'
# Linux: smem -P 'php-fpm' -c 'pid pss uss command' (when available)
# Pool: pm.status_path = /fpm-status — restrict access internally.
# Match listen queue and max children reached to the 5xx timestamps.
Check whether the database, Redis and external APIs can handle that many concurrent requests. Raising pm.max_children without memory may trigger OOM and worse 502s. Inspect nginx fastcgi_connect_timeout and fastcgi_read_timeout; read timeout limits the gap between reads. The broader sequence is in the upstream timeout guide.
Rule out other 502 causes
Confirm the Unix socket exists, nginx can access it, fastcgi_pass points to it, and FPM is running without restarts. Connection refused suggests an unavailable endpoint; upstream prematurely closed connection describes a close after connection. Both need more log evidence. A growing queue without worker crashes suggests load or long requests. For an outer CDN 5xx, compare TTFB and total time with the internal request ID.
How we made this guide
Status fields and pool directives were checked against PHP manuals; nginx behavior against its FastCGI module. The 2 GiB/100 MiB example is explicitly hypothetical. enterno.io has a separate Apache worker configuration, whose historical limit cannot be used as an FPM pool measurement. SerpAPI provided RU/EN search snapshots. Wordstat region 225 had no estimate for the exact phrase and 2 for php fpm 502.
FAQ
Why is max children reached recorded without a 502?
A brief peak may fit in the queue and finish before the gateway deadline. Correlate time and queue depth.
Is increasing pm.max_children enough?
No. Check memory, request duration and dependencies.
Why 502 instead of 504?
502 typically follows an invalid or broken response; 504 follows a gateway timeout. Verify the actual emitting hop.
Can FPM status be public?
Avoid it. Restrict access and collect metrics over an internal protected route.