A web server like Nginx can't run PHP. It passes each PHP request, over the FastCGI protocol, to a separate service that does the work and sends back the result: that's PHP-FPM's job. The PHP documentation describes it as PHP's primary FastCGI implementation, with features mostly useful for heavily loaded sites. With Apache, PHP-FPM replaces the old mod_php and is used through mod_proxy_fcgi.
How PHP-FPM works
A master process reads the configuration and manages child processes, the workers, grouped into pools. Each pool is defined in a configuration file, often one per site, with:
userandgroup: the processes' system identity. Two sites in two pools under two different users can't read each other's files if permissions are set correctly;listen: the address where the pool waits for requests, a Unix socket or an IP address and port;pmand its directives: the number of workers;- PHP values specific to the pool, with
php_valueorphp_admin_value. The latter can't be overridden byini_set()from a script.

The settings that matter
pm.max_children sets the maximum number of workers, and therefore of PHP requests handled at the same time. Too low, and visitors wait; too high, and the server runs out of memory. A simple estimate is to divide the memory set aside for PHP by the average consumption of one worker, measured on your site.
pm.max_requests respawns a worker after a set number of requests; the documentation recommends it to work around memory leaks in third-party libraries. The default value, 0, never respawns.
request_slowlog_timeout and slowlog record the PHP call stack of overly slow requests: a valuable tool for finding the plugin that slows WordPress down. request_terminate_timeout kills a stuck worker when max_execution_time isn't enough.
Security
The PHP documentation is unequivocal: PHP-FPM must never be reachable from an untrusted network. A client able to open a FastCGI connection controls the request's configuration, including auto_prepend_file, and can therefore execute arbitrary code. Prefer a Unix socket when the web server runs on the same machine, and otherwise restrict the allowed clients with listen.allowed_clients.
For WordPress
- One pool per site on a VPS hosting several WordPress installs: a compromised plugin stays confined to its own user.
- Harden PHP at the pool level: open_basedir, disabling system functions and the other settings in our guide to hardening PHP on a hosting account. Note that disable_functions can only be added to in a pool, not replaced.
- Reload PHP-FPM after a configuration or version change, and stay on a supported PHP branch (see end-of-life PHP versions).
- Enable OPcache: it's shared between workers and saves recompiling scripts on every request.
On shared hosting, the host configures these pools for you; usually only the PHP version and a few PHP values are left up to you.
Common mistakes
Leaving PHP-FPM listening on 0.0.0.0, cranking up pm.max_children until memory runs out, running every site in the same pool, or forgetting to reload the service after a change and assuming the setting is active.