How to monitor PHP-FPM worker saturation: Best 2026

Learn how to monitor PHP-FPM worker saturation to boost server speed. Read our 2026 guide and optimize metrics today!

Glowing fiber optics shifting from blue to red, representing intense server data processing.

If you run a website built with PHP, you have probably heard of PHP-FPM. It handles every request that comes to your site. When too many requests hit your server at once, PHP-FPM worker saturation becomes a real problem. Your pages load slowly. Visitors leave. This guide will teach you how to monitor PHP-FPM worker saturation step by step. By the end, you will know exactly what to watch, how to set up alerts, and how to fix issues before they hurt your site.

What Is PHP-FPM Worker Saturation?

PHP-FPM uses a pool of worker processes to handle web requests. Think of each worker as a chef in a kitchen. When orders pile up and all chefs are busy, new orders must wait. That wait is PHP-FPM worker saturation. Let us break it down.

Understanding Worker Pool Dynamics

When you install PHP-FPM, it creates a pool of workers. Each worker picks up one request at a time. The pool has three key settings:

  • pm.start_servers: Workers that start when PHP-FPM boots up.
  • pm.min_spare_servers: The minimum idle workers kept ready.
  • pm.max_children: The hard ceiling on total workers allowed.

In dynamic mode, PHP-FPM adds workers when traffic rises and removes them when traffic drops. The pool grows and shrinks within the limits you set.

The Saturation Formula: Active Processes vs. pm.max_children

PHP-FPM worker saturation happens when this condition is true:

Active Processes = pm.max_children

When every worker slot is full, new requests queue up. The queue grows. Response times spike. You can measure saturation as a percentage:

Saturation % = (Active Processes / pm.max_children) × 100

A value above 80% means you are close to full saturation. A value at 100% means your site is likely dropping requests.

Why Saturation Kills Website Performance

When PHP-FPM worker saturation occurs, several bad things happen at once:

  • New visitors get 502 Bad Gateway errors.
  • Existing visitors see pages load in 10 seconds or more.
  • The listen queue fills up and the kernel starts dropping connections.
  • Database connections pile up, causing even more slowdowns.

Learning to monitor PHP-FPM worker saturation early stops these problems before users notice them.

Key Metrics to Monitor for PHP-FPM Worker Saturation

You cannot fix what you cannot see. Here are the five key metrics that tell you the health of your PHP-FPM pool.

Active Processes and Idle Workers

Active processes handle current requests. Idle workers sit ready for new ones. If idle workers stay at zero for long periods, PHP-FPM worker saturation is happening right now.

Listen Queue Depth and Backlog

The listen queue holds requests waiting for a free worker. A growing queue means demand exceeds capacity. If the queue hits the backlog limit, the kernel rejects new connections entirely.

Max Children Reached Counter

This counter tracks how many times PHP-FPM hit the pm.max_children limit since it started. A rising number means your pool size is too small for your traffic. It is one of the clearest signs of PHP-FPM worker saturation.

Slow Requests and Request Duration

PHP-FPM can log requests that take longer than a threshold you set. Long request duration often points to slow code or database queries. Tracking slow requests helps you find the root cause behind saturation.

Socket Backlog and Kernel-Level Drops

The operating system has its own socket backlog. When PHP-FPM cannot accept connections fast enough, the kernel drops them. You can see these drops in /proc/net/netstat. Kernel drops are a strong signal of severe PHP-FPM worker saturation.

Step 1: Enable the PHP-FPM Status Endpoint Safely

Before you can monitor PHP-FPM worker saturation, you need to turn on the built-in status page. This page shows live data about your worker pool.

Configure pm.status_path in Your Pool Settings

Open your PHP-FPM pool configuration file. It is usually found at /etc/php/8.x/fpm/pool.d/www.conf. Add or edit this line:

pm.status_path = /fpm-status

You can also enable the ping path for health checks:

ping.path = /fpm-ping

Save the file after making changes.

Secure the Status Page with Access Controls

The status page shows sensitive server data. Never leave it open to the public. Add access control in the same pool config file:

pm.status_path = /fpm-status

Then in your Nginx server block, restrict access by IP:

  • location = /fpm-status { allow 127.0.0.1; deny all; fastcgi_pass unix:/run/php/php-fpm.sock; include fastcgi_params; }

This ensures only your local machine can read the status page.

Test the Status Endpoint Locally with curl

Restart PHP-FPM to load the new settings:

sudo systemctl restart php8.2-fpm

Then test with curl:

curl http://127.0.0.1/fpm-status

You should see output that includes pool name, process manager type, active processes, idle processes, and more. If you see this data, your status endpoint is working and you are ready to monitor PHP-FPM worker saturation.

Step 2: Monitor PHP-FPM Using Command-Line Tools

Command-line tools give you a fast way to check PHP-FPM worker saturation without installing heavy software.

Query Status with cgi-fcgi and Parse Output

Install the cgi-fcgi tool if you do not have it:

sudo apt install libfcgi0ldbl

Then query the status endpoint directly through the socket:

SCRIPT_NAME=/fpm-status SCRIPT_FILENAME=/fpm-status REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/php-fpm.sock

The output shows active processes, idle workers, max children reached, and listen queue len. You can pipe this into grep to extract specific values for scripts.

Check Socket Backlog with ss Command

The ss command shows the current state of sockets on your server. Run:

ss -lnt | grep php-fpm

Look at the Send-Q and Recv-Q values. A high Send-Q on the PHP-FPM socket means connections are piling up faster than workers can accept them. This is a clear sign of PHP-FPM worker saturation at the kernel level.

Monitor Kernel Listen Drops via /proc/net/netstat

The Linux kernel tracks how many connections it drops because the listen queue is full. Check it with:

cat /proc/net/netstat | grep -i listen

Look for the ListenDrops field. If this number grows quickly over time, your server is rejecting connections due to PHP-FPM worker saturation. You can script this check to run every minute and log the delta.

Step 3: Set Up Automated Monitoring with Prometheus and Grafana

For long-term monitoring of PHP-FPM worker saturation, you need a system that collects data over time and shows it on dashboards. Prometheus and Grafana are the best free tools for this job.

Install and Configure the PHP-FPM Exporter

The PHP-FPM exporter reads the status page and converts it into Prometheus metrics. Download it from GitHub and place it on your server. Create a simple config file that points to your status URL:

  • scrape-uri: http://127.0.0.1/fpm-status?json
  • listen-address: :9253

Start the exporter as a systemd service. Then add a scrape job in your prometheus.yml file to pull metrics every 15 seconds.

Build a Saturation Dashboard in Grafana

Open Grafana and create a new dashboard. Add panels for these key metrics:

  • php_fpm_active_processes (gauge)
  • php_fpm_idle_processes (gauge)
  • php_fpm_max_children_reached (counter, rate over 5m)
  • php_fpm_listen_queue (gauge)
  • php_fpm_slow_requests (counter, rate over 5m)

Set the y-axis on the active processes panel to show pm.max_children as a reference line. When the active line touches the max line, you know PHP-FPM worker saturation is happening.

Configure Alert Rules for Worker Saturation

In Grafana, create alert rules to notify you before saturation causes outages. Good starting thresholds:

  • Warning: Active processes above 80% of pm.max_children for 5 minutes.
  • Critical: Active processes at 100% of pm.max_children for 2 minutes.
  • Warning: Listen queue above 50 for 3 minutes.
  • Critical: Max children reached rate above 1 per minute.

Send alerts to Slack, email, or PagerDuty so your team can act fast.

Step 4: Diagnose the Root Cause of PHP-FPM Saturation

Monitoring tells you saturation is happening. Diagnosis tells you why. Here are the three most common causes of PHP-FPM worker saturation.

Application-Level Bottlenecks: Slow PHP Code

Slow PHP code holds workers longer than needed. A single request that takes 5 seconds instead of 200ms ties up a worker 25 times longer. Use tools like Xdebug, Blackfire, or New Relic to profile your PHP code. Look for functions that run database queries in loops, load large files into memory, or make unoptimized API calls.

Database or External Service Latency

Often the PHP code itself is fine, but the database behind it is slow. Check your MySQL or PostgreSQL slow query log. Look for missing indexes, table locks, or long-running transactions. External APIs can also cause PHP-FPM worker saturation if they respond slowly. Add timeouts to every external call in your code.

Traffic Spikes vs. Chronic Undercapacity

Not all saturation is the same. A sudden spike from a viral post is different from steady growth that outpaces your server. Look at your traffic graphs:

  • If saturation happens in short bursts, you need better caching or a CDN.
  • If saturation grows steadily over weeks, you need more workers or another server.

Step 5: Tune pm.max_children for Your Workload

Once you understand the cause, you can tune PHP-FPM worker saturation by setting the right number of workers.

Calculate Optimal Worker Count Based on Available Memory

Each PHP-FPM worker uses memory. A typical WordPress request uses 40-80MB. Use this formula:

pm.max_children = Available Memory for PHP / Memory per Worker

For example, if you have 4GB of RAM and your server uses 1.5GB for the OS and database, you have 2.5GB left. At 60MB per worker:

2560MB / 60MB = ~42 workers

Set pm.max_children to 40 to leave a safety margin.

Choose Between Dynamic, Static, and On-Demand Process Modes

Mode Best For Memory Use
static Predictable, high traffic Highest, but fastest response
dynamic Variable traffic patterns Moderate, scales with load
ondemand Low traffic, many pools Lowest, but slower cold start

For most small websites, dynamic mode gives the best balance. For high-traffic sites, static mode avoids the overhead of spawning new workers during traffic spikes.

Validate Configuration Changes Without Downtime

Before reloading PHP-FPM, test your config syntax:

php-fpm8.2 -t

If the test passes, reload gracefully:

sudo systemctl reload php8.2-fpm

A reload does not kill existing connections. Active workers finish their current requests before the new config takes effect. Watch your Grafana dashboard for 10 minutes after the reload to confirm PHP-FPM worker saturation levels improve.

FAQ: Common Questions About Monitoring PHP-FPM Worker Saturation

Q: How often should I check for PHP-FPM worker saturation?

With Prometheus and Grafana, data is collected every 15 seconds. You get near-real-time visibility. At minimum, check your dashboard once a day.

Q: Can I monitor PHP-FPM worker saturation without Prometheus?

Yes. You can write a simple bash script that curls the status page every minute and logs the values. Prometheus just makes it easier to see trends and set alerts.

Q: What is a safe saturation level?

Keep active processes below 80% of pm.max_children. If you regularly see 90% or higher, you need more workers or faster code.

Q: Does increasing pm.max_children always fix saturation?

No. If your server runs out of RAM, adding more workers causes swapping and makes things worse. Always calculate based on available memory first.

Q: How do I know if kernel drops are affecting my site?

Check /proc/net/netstat for ListenDrops. If the number grows by hundreds per minute, users are getting connection refused errors. Fix the root cause before increasing the socket backlog.

Conclusion: Building a Sustainable PHP-FPM Monitoring Strategy

Monitoring PHP-FPM worker saturation is not a one-time task. It is an ongoing practice. Start by enabling the status endpoint. Then set up Prometheus and Grafana to collect and display your metrics. Create alert rules so you learn about problems before your users do. When saturation hits, diagnose the root cause, whether it is slow code, database latency, or not enough workers. Finally, tune pm.max_children based on real data, not guesswork.

The key takeaway is simple: you cannot manage what you do not measure. With the steps in this guide, you now have a clear path to monitor PHP-FPM worker saturation, catch issues early, and keep your website fast and reliable for every visitor.