Web hosting

PHP-FPM

Definition

PHP-FPM (FastCGI Process Manager) is PHP's official FastCGI process manager. It runs groups of PHP processes, called pools, that receive the scripts passed on by the web server (Nginx, Apache, Caddy); each pool can have its own system user, limits and php.ini, which isolates sites from each other.

PHP-FPM, Web hosting

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:

  • user and group: 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;
  • pm and its directives: the number of workers;
  • PHP values specific to the pool, with php_value or php_admin_value. The latter can't be overridden by ini_set() from a script.
Comparison of PHP-FPM's three process management modes. static: a fixed number of processes equal to pm.max_children, always ready but using memory permanently, suited to a server dedicated to one busy site. dynamic: pm.start_servers at startup, between pm.min_spare_servers and pm.max_spare_servers idle processes, capped at pm.max_children, the usual compromise. ondemand: no idle processes, created on demand up to pm.max_children, stopped after pm.process_idle_timeout, economical for many small sites.
The pm setting decides how many PHP processes wait for requests, and therefore how much memory is used.

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.

Video: “How Nginx and PHP-FPM turn a web request into code” (Chris Fidao)

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.

Further reading

  • Article End-of-life PHP versions: schedule, risks and migration

Sources

  1. PHP Manual: FastCGI Process Manager (FPM) (external link, opens in a new tab)
  2. PHP Manual: FPM configuration (external link, opens in a new tab)
  3. WordPress Advanced Administration: Nginx (external link, opens in a new tab)

All definitions

WordPress security, without the noise

One e-mail when something matters: new attacks seen in the wild, plugin updates and practical guides. No spam, unsubscribe in one click.

Start free, go Pro when you’re ready

The free version already hides WordPress and moves the login page. Pro adds aliases, two-factor authentication and monitoring.