FundamentalsBeginner

What is PHP-FPM? FastCGI Process Manager Explained

PHP-FPM (FastCGI Process Manager) explained: what it is, how it works, configuration essentials (pm.max_children, pool management), monitoring, and when to use PHP-FPM vs alternatives.

10 min read
Atatus Team
Updated October 1, 2026
6 sections
01

What is PHP-FPM?

The modern way to run PHP in production

PHP-FPM (FastCGI Process Manager) is a daemon that manages a pool of PHP worker processes to handle requests. It replaces the older mod_php approach of embedding PHP into Apache.

Nginx and Apache (via mod_proxy_fcgi) communicate with PHP-FPM over FastCGI — the web server receives HTTP requests, forwards them to PHP-FPM, PHP-FPM executes the PHP code and returns the response.

PHP-FPM has been the production-standard way to serve PHP since ~2012. If you are running Nginx + PHP, you are almost certainly running PHP-FPM.

The name is often written php-fpm, PHP FPM, or just FPM. All refer to the same thing.

02

How PHP-FPM works

The process model you need to understand

PHP-FPM manages worker processes grouped into "pools". Each pool has its own user, group, listening socket, and configuration.

When a request arrives, the web server (Nginx, Apache) hands it to PHP-FPM via FastCGI. PHP-FPM assigns an idle worker to execute the PHP script.

The worker executes the request, returns the response, and goes back to the pool. Workers persist across requests (reducing startup cost) but are periodically recycled to prevent memory leaks.

If all workers are busy and a request arrives, PHP-FPM either spawns a new worker (if under pm.max_children) or queues the request.

03

PHP-FPM configuration: pm.max_children and friends

The settings that determine production behavior

pm (process manager): static, dynamic, or ondemand. "dynamic" is the most common — pool size adjusts based on load.

pm.max_children: the maximum number of worker processes. The single most important setting. Calculate as: available_memory_for_PHP / avg_memory_per_worker. On a 4GB server with 100MB per worker, max_children ≈ 30.

pm.start_servers: how many workers to spawn at startup (dynamic mode). Should be around (max_spare_servers + min_spare_servers) / 2.

pm.min_spare_servers / pm.max_spare_servers: idle worker thresholds. Workers below min get spawned; workers above max get killed.

pm.max_requests: how many requests a worker handles before being recycled. 500–1000 is typical. Lower if your code leaks memory.

request_terminate_timeout: kill workers that run longer than this. Prevent single slow queries from hanging the pool.

04

Monitoring PHP-FPM

The signals that matter in production

Enable the status page: in your PHP-FPM pool config, set pm.status_path = /status. Hit this via a protected endpoint in your web server for a live view.

Key metrics: accepted conn (total requests served), listen queue (requests waiting), active processes (busy workers), idle processes (idle workers), max_children_reached (how often you hit the ceiling).

Alert on: max_children_reached > 0 (you need more workers), listen queue > 0 for sustained periods (requests queuing), slow requests count rising (something is blocking).

Slow log: set slowlog = /var/log/php-fpm/slow.log and request_slowlog_timeout = 5s to log any request taking longer than 5 seconds. Essential for finding slow PHP code paths.

Atatus PHP APM auto-instruments PHP-FPM: per-request latency, memory usage, FPM pool stats, and correlated SQL queries — all in one UI.

05

PHP-FPM vs mod_php vs Swoole vs RoadRunner

The PHP runtime landscape in 2026

mod_php (Apache module): PHP embedded in Apache. Simpler setup but each Apache child process has PHP in memory — heavy. Not recommended for new deployments.

PHP-FPM: the current production standard. Worker pool managed independently from the web server. Pairs with Nginx or Apache (via proxy_fcgi).

Swoole: PHP extension that provides async I/O and long-running processes. For PHP applications that need WebSocket, coroutines, or real-time features.

RoadRunner: Go-based PHP application server. Each worker is a long-running PHP process. Much faster than FPM for frameworks that support it (Laravel Octane uses RoadRunner).

Laravel Octane: wraps Swoole, RoadRunner, or FrankenPHP. Dramatic throughput improvement (3–10x) over FPM for Laravel apps.

FrankenPHP: a modern application server written in Go that bundles PHP; also powers Laravel Octane.

06

Common PHP-FPM problems

Issues to recognize and fix

"pm.max_children setting too low": increase if listen queue is non-zero. Verify available memory first — you can't have unlimited workers.

Slow endpoints exhaust workers: one slow query holding workers for 30 seconds blocks the entire pool. Fix the slow query, or add request_terminate_timeout.

Memory leaks: workers growing over time. Lower pm.max_requests to recycle more aggressively, but find the root cause (unclosed resources, static caches).

OPcache not enabled: dramatic performance regression without OPcache. Always enable in production.

Multiple pools misconfigured: separate pools for admin, API, cron workers lets you tune each independently.

Key Takeaways

  • PHP-FPM = FastCGI Process Manager, the daemon that manages PHP worker pools.
  • Nginx/Apache forward requests to PHP-FPM via FastCGI; workers execute PHP and return responses.
  • Key config: pm.max_children (worker ceiling), pm.max_requests (recycle frequency), request_terminate_timeout (kill slow requests).
  • Monitor pm.status_path for listen queue, active/idle workers, max_children_reached.
  • Enable slowlog with request_slowlog_timeout to catch slow endpoints.
  • Alternatives: Swoole, RoadRunner, FrankenPHP, Laravel Octane — significant throughput gains over FPM for compatible frameworks.
Get started today

Monitor your applications with Atatus

Put the concepts from this guide into practice. Set up full-stack observability in minutes with no credit card required.

No credit card required14-day free trialSetup in minutes

Related guides