Optimizing PHP-FPM for Blazing Fast Websites

PHP powers over 70% of all websites, yet it has a reputation for being slow compared to other languages. But with some smart optimization of PHP-FPM, you can achieve stunning performance. This comprehensive guide will show you how.

Why PHP Performance Matters

While PHP simplicity has fueled its widespread adoption, performance issues can quickly cause problems at scale:

  • Slow response times frustrate users and hurt conversion rates
  • Spikes in traffic can overwhelm servers and crash sites
  • More server resources are needed to handle the same workloads

By optimizing PHP-FPM configuration, we can achieve big performance wins without having to throw more hardware at the problem.

Introducing the PHP Fast Process Manager (PHP-FPM)

PHP-FPM is the default process manager for modern PHP deployments. It handles efficiently spawning, managing and killing PHP handler processes to serve each request.

Here‘s a quick overview:

  • Launches a set number of child processes on startup
  • Maintains a pool of idle processes during operation
  • Routes incoming requests from the web server to child processes
  • Scales up/down to meet demand without delay

Tuning PHP-FPM is essential for getting the most out of your PHP deployment. Suboptimal config can leave needless resources tapped or cripple your site under heavy loads.

Why Optimize PHP-FPM Configuration?

Out of the box configuration leaves a lot of performance on the table:

  • Too few PHP workers struggle under typical loads
  • Too many workers waste RAM for no good reason
  • Slow process scaling fails during traffic spikes

With some targeted tweaks, we can achieve:

  • Faster response times
  • Support for more concurrent users
  • Protection against traffic surges
  • Efficient resource usage
  • Delayed hardware upgrades

php-fpm.conf Optimization Settings

The main php-fpm config file has a few handy settings for stability:

emergency_restart_threshold

If this many child processes crash within a window defined by emergency_restart_interval, PHP-FPM will gracefully restart itself to clear any issues.

emergency_restart_threshold 10

emergency_restart_interval

The interval (in seconds) used for checking emergency_restart_threshold.

emergency_restart_interval 1

process_control_timeout

Max time in seconds to wait for child processes to handle SIGTERM/SIGQUIT before force killing. Gives worker processes a chance to finish up and exit cleanly.

process_control_timeout 10s

Optimizing Pool Configuration

The meat of optimization happens inside the pool conf files. This is where we define how many PHP handlers to run and how they are managed.

Pools are set up by website domain, using pool name www, site1, site2, etc.

[www] ;Website main domain

[site1] ; additional website

There will be a pool conf file present for each defined pool, often inside /etc/php-fpm.d.

The main settings we care about:

pm – Process Manager

Defines how processes are launched and managed:

static – fixed number of workers

dynamic – workers scale between min/max bounds

ondemand – workers created per request

pm.max_children

Limits maximum number of child processes regardless of process manager.

pm.start_servers

Number of workers to launch at startup.

pm.min/max_spare_servers

Bounds for number of idle backup workers for dynamic pm.

pm.max_requests

Max requests each child process should handle before recycle.

Choosing a Process Manager

There are pros and cons to each process manager strategy:

static pm

Pros

  • Simple configuration
  • Max performance and efficiency

Cons

  • No automatic scaling
  • Risk of insufficient workers
  • Wasted resources if over-provisioned

Best for predictable loads.

dynamic pm

Pros

  • Self-tuning based on load
  • Graceful scaling

Cons

  • Slower process scaling
  • Potential stability issues

Works for fluctuating traffic.

ondemand pm

Pros

  • Great for low resource usage
  • No unnecessary idle workers

Cons

  • Sluggish process startup under load
  • Stability concerns during scaling events

Good option for low/bursty traffic patterns.

Real-World Optimization Example

Let‘s walk through a before/after PHP-FPM optimization example.

We‘ll look at some benchmark results from the following budget VPS:

  • 2 CPU Cores
  • 4GB RAM
  • Ubuntu 20.04

This is hosting a high traffic WordPress site. Under peak loads, CPU usage would hit 100% and load times would spike.

The default PHP-FPM config had pm set to ondemand with pretty basic settings:

pm = ondemand
pm.max_children = 10

This is very conservative and keeps resource usage slim, but struggles during traffic surges when incoming requests pile up waiting for new PHP workers to start.

After analyzing access logs and current resource limits, we switch the config to:

pm = static
pm.max_children = 50
pm.max_requests = 500   

By pre-forking a fixed number of workers, we ensure capacity to handle typical daily peaks without delay spinning up new processes.

The results of this optimization were impressive:

  • Page load times reduced by 35%
  • CPU usage down from 100% to 60% in benchmarks
  • Support for 2x more concurrent users

Most importantly, the site can now easily power through rush hour without breaking a sweat!

And there is still plenty of headroom to grow traffic further before needing to upgrade hosting.

Common Pitfalls & Issues

While the performance gains from optimizing PHP-FPM can be incredible, it‘s easy to go wrong and cause new issues:

Too Many Child Processes

Launching a crazy number of PHP workers may handle high loads, but at the cost of slow database queries and risk of hitting process user limits.

Make sure to balance with hardware capacity. Check if CPU cores or RAM maxes out before php-fpm does.

OOM Killer

Pushing PHP memory usage too high triggers the kernel‘s out-of-memory process killer. This abruptly terminates processes to free up resources.

Unfortunately it often kills important ones like MySQL and takes down sites.

Watch for OOM messages in logs as a warning sign.

High Load Averages

While CPU usage may look fine, a server can still be overloaded. Load averages indicate jobs waiting for free CPU resources.

If consistently higher than cores (e.g. 8.0 on a 4 CPU server), reduce PHP workers.

CORS Errors

Exceeding open file limits causes failed requests and CORS issues.

Check with ulimit -Sn and increase with Plesk/cPanel or /etc/security/limits.conf.

Alternatives for High Performance

While proper PHP-FPM optimization offers big wins, other solutions exist:

  • Redis – PHP sessions, object caching
  • Varnish – Front-end cache
  • Nginx microcaching – Simple caching plugin
  • CDN – Distribute static assets
  • LiteSpeed – Drop-in high efficiency web server replacement
  • HHVM – Facebook‘s high performance PHP engine

For WordPress sites, advanced page caching from plugins like LiteSpeed Cache and WP Rocket can also help minimize backend PHP load.

Profiling & Monitoring Optimization Gains

To dial in ideal settings, we need visibility into how changes impact performance and resources.

Useful metrics to monitor:

  • Load Averages – System load
  • Web Server Stats – Requests, latency, traffic
  • php-fpm status – Workers, accepts/sec
  • Database Metrics – Connections, queries/sec
  • OOM Events – Out of memory killers

Tools like New Relic APM give deep visibility for free on low traffic sites. Grafana and Prometheus provide open source monitoring options.

For WordPress, check out P3 Plugin Profiler.

Squeeze Every Last Drop from Your Servers

With soaring web hosting costs, getting the most from your servers is key. Optimizing PHP-FPM configuration unleashes significant extra horsepower.

We‘ve covered the main settings and techniques to achieve PHP high performance.

The abstract concept of process management comes alive seeing real world gains of 2X more users supported after tuning.

Now you have the fundamental framework to tweak and tailor PHP-FPM for lighting fast Pareto performance on your websites.

So try out a few experiments and let us know what big wins you uncover!