PHP-FPM pm.max_children: how do you actually calculate it
I keep seeing the advice “set max_children to RAM / average worker memory” but in practice this gives different results depending on how you measure worker memory.
Top shows one thing, /proc/$pid/status VmRSS shows another, /proc/$pid/smaps is different again.
What is the correct measurement to use for capacity planning?
Use VmRSS from /proc/$pid/status after the worker has served a few hundred requests and is warm. The first few requests will show lower memory because PHP has not loaded all code paths yet. Let the process warm up, then sample.
The formula is: (Total RAM - OS overhead - other services) / average warm worker RSS. OS overhead is usually 200-400MB on a dedicated PHP host. Leave 20% headroom for spikes.
pm = dynamic is safer than pm = static on servers that handle variable load. Set pm.min_spare_servers and pm.max_spare_servers to keep some warmed workers around without holding all the memory constantly.
pm.max_requests = 500 is worth setting on any app that has third-party libraries with potential leaks. It forces workers to restart periodically. Performance cost is negligible, leak protection is real.
had a fun one where wrkers kept dying but max_children looked fine. turns out pm.process_idle_timeout was set to 10s and killing workers during burst. took embarrasingly long to find
status.listen is useful for this. Point php-fpm status at a local socket and poll it. If the queue depth goes above zero regularly, max_children is too low.