Docs / Web Servers / How to Configure Nginx for Optimal PHP-FPM Performance

How to Configure Nginx for Optimal PHP-FPM Performance

By Admin · Mar 15, 2026 · Updated Apr 24, 2026 · 413 views · 3 min read

The combination of Nginx and PHP-FPM is the gold standard for PHP application hosting. Properly tuning this stack can handle thousands of requests per second. This guide covers optimal configuration for both Nginx and PHP-FPM.

PHP-FPM Pool Configuration

# /etc/php/8.3/fpm/pool.d/www.conf

[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data

# Process management
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 1000

# Status page (for monitoring)
pm.status_path = /fpm-status
ping.path = /fpm-ping

# Logging
access.log = /var/log/php-fpm/access.log
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s
request_terminate_timeout = 30s

Calculating max_children

# Formula: max_children = (Available RAM - OS/Other services) / Average PHP process size

# Check average PHP-FPM process size:
ps aux | grep php-fpm | awk "{sum += \$6; count++} END {print sum/count/1024 \"MB\"}"
# Typical: 30-50MB per process

# Example calculation:
# Server RAM: 8GB
# OS + MySQL + Nginx: ~2GB
# Available for PHP: 6GB = 6144MB
# Average PHP process: 40MB
# max_children = 6144 / 40 = 153
# Set to 150 (leave some headroom)

Nginx FastCGI Configuration

# /etc/nginx/conf.d/php-fpm.conf

# FastCGI cache (optional, significant performance boost)
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=PHPCACHE:10m max_size=1g inactive=60m;

server {
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # Buffer settings
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;

        # Timeouts
        fastcgi_connect_timeout 5s;
        fastcgi_send_timeout 60s;
        fastcgi_read_timeout 60s;

        # Cache (for cacheable pages)
        fastcgi_cache PHPCACHE;
        fastcgi_cache_valid 200 10m;
        fastcgi_cache_methods GET HEAD;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

PHP.ini Optimization

# /etc/php/8.3/fpm/php.ini

# OPcache (CRITICAL for performance)
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0  # Set to 1 for development
opcache.jit=1255
opcache.jit_buffer_size=128M

# Memory and execution
memory_limit=256M
max_execution_time=30
max_input_vars=5000

# Upload limits
upload_max_filesize=64M
post_max_size=64M

# Session
session.gc_maxlifetime=86400

Monitoring PHP-FPM

# Enable status page in Nginx
location /fpm-status {
    access_log off;
    allow 127.0.0.1;
    deny all;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

# Check status
curl http://localhost/fpm-status

# Key metrics:
# active processes — Currently handling requests
# idle processes — Waiting for requests
# listen queue — Requests waiting for a free process (should be 0)
# max children reached — Pool exhaustion events (increase max_children)

Was this article helpful?