How to configure PHP-FPM pool settings for high concurrency
Adjust PHP-FPM pool parameters to handle thousands of simultaneous requests without crashing. Set worker limits, process recycling, and memory thresholds on Ubuntu 24.04 with PHP 8.3.
This guide shows you how to tune PHP-FPM pool settings to handle high concurrency without crashing your application. You will adjust the process manager settings for PHP 8.3.x on Ubuntu 24.04 to support thousands of simultaneous requests. These changes ensure your server scales smoothly under load.
Prerequisites
- Operating system: Ubuntu 24.04 LTS
- PHP version: 8.3.x installed via
aptorpecl - Web server: Nginx 1.24.x or Apache 2.4.x
- Privileges: Root access or sudo rights
- PHP-FPM pool file location:
/etc/php/8.3/fpm/pool.d/www.conf
Step 1: Identify the current pool configuration
Locate the default pool configuration file for your PHP version. Open the file to see the current process manager settings. You need to know the existing values before changing them to avoid breaking the service.
sudo nano /etc/php/8.3/fpm/pool.d/www.conf
You will see lines defining the process manager type and worker limits. The default configuration usually uses pm = static or pm = dynamic with low limits. High concurrency requires changing these values.
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
Step 2: Switch to dynamic process management
Change the process manager to dynamic. This allows PHP-FPM to spawn new processes as needed and recycle old ones. Static mode creates a fixed number of processes that cannot scale up. Dynamic mode is essential for handling traffic spikes.
pm = dynamic
Step 3: Increase the maximum number of children
Set pm.max_children to a value that matches your server's memory capacity. A safe starting point for high concurrency is 150 to 200 processes. Calculate this based on your available RAM and the memory footprint of your PHP application. If your app uses 100MB per process, 200 processes require 20GB of RAM.
pm.max_children = 200
Step 4: Adjust start servers and spare servers
Configure the initial number of processes and the pool of idle workers. Set pm.start_servers to 25 to start with enough workers for initial traffic. Set pm.min_spare_servers to 50 to keep a baseline of idle processes ready. Set pm.max_spare_servers to 150 to allow the pool to grow quickly when demand increases.
pm.start_servers = 25
pm.min_spare_servers = 50
pm.max_spare_servers = 150
Step 5: Set process recycling limits
Enable process recycling to prevent memory leaks from accumulating over time. Set pm.max_requests to 1000. This forces PHP-FPM to restart a process after it handles 1000 requests. This keeps the worker processes fresh and prevents them from holding onto stale memory.
pm.max_requests = 1000
Step 6: Configure the error log path
Ensure the error log is writable and points to a specific location. Set catch_workers_output to yes to capture stderr from workers. This helps you debug issues when a worker crashes under load.
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php-fpm.error.log
Step 7: Reload PHP-FPM to apply changes
Save the configuration file and reload the PHP-FPM service. Do not restart the service immediately, as this kills all processes. Reloading allows new settings to take effect without dropping active connections.
sudo systemctl reload php8.3-fpm
Verify the installation
Check the active processes to confirm the new settings are applied. Run the command to list the running PHP-FPM processes. You should see a count close to your pm.start_servers value.
sudo systemctl status php8.3-fpm
● php8.3-fpm.service - The PHP 8.3 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.3-fpm.service; enabled)
Active: active (running) since Mon 2024-05-20 10:00:00 UTC; 2h ago
Tasks: 25 (limit: 200)
Memory: 2.5G
CGroup: /system.slice/php8.3-fpm.service
├─1234 php-fpm: master process (/etc/php/8.3/fpm/pool.d/www.conf)
├─1235 php-fpm: pool www
├─1236 php-fpm: pool www
└─1237 php-fpm: pool www
Use the pm.status page to see real-time stats. Access the status page via your web server or curl. Look for the active processes count matching your configuration.
curl http://localhost/status
Troubleshooting
If PHP-FPM crashes or fails to start, check the error logs. Look for messages about out-of-memory or pm.max_children limits being hit. Increase the memory limit or reduce the number of children if the server runs out of RAM.
sudo tail -f /var/log/php-fpm.error.log
If you see Too many open files errors, increase the file descriptor limit. Edit /etc/security/limits.conf to set * soft nofile 65535 and * hard nofile 65535. Then reboot or log out and back in.
sudo nano /etc/security/limits.conf
If Nginx returns 502 Bad Gateway, check if PHP-FPM is listening on the correct socket. Ensure the socket path in Nginx matches the one defined in PHP-FPM. Verify the socket exists at /run/php/php8.3-fpm.sock.
Monitor memory usage with free -m. If memory is near 100%, reduce pm.max_children or increase server RAM. High concurrency requires balancing CPU and memory resources carefully.