Stop the Bleeding: Tuning PHP-FPM for High-Concurrency Workloads
If you are still serving PHP applications using Apache's mod_php prefork worker in 2012, you are voluntarily burning money. I recently audited a high-traffic e-commerce cluster in Oslo that was collapsing under just 500 concurrent users. The culprits? Bloated Apache processes consuming 80MB of RAM each, even for static asset requests.
The solution isn't adding more RAM—it's changing the architecture. By decoupling the web server from the PHP interpreter using Nginx and PHP-FPM (FastCGI Process Manager), we dropped memory usage by 60% and latency by 400ms. But installing FPM isn't enough; the defaults are conservative garbage meant for low-traffic blogs. If you want raw performance, you need to tune the process manager manually.
The Architecture: Why FastCGI Wins
With mod_php, every Apache child process loads the entire PHP interpreter. When a client downloads a 5MB PDF, that hefty process sits idle, wasting memory, waiting for the slow client to finish. Nginx acts differently. It serves static content instantly with a tiny memory footprint. When it encounters a .php file, it proxies the request to the PHP-FPM daemon via a local socket or TCP.
This separation allows us to tune the PHP pool independently of the web server connections. It is the only way to solve the C10k problem on reasonable hardware.
Configuring the Pool: Static vs. Dynamic
The most debated setting in /etc/php-fpm.d/www.conf (on CentOS 6) is the process manager control: pm.
- pm = dynamic: The default. Spawns processes as needed. Good for shared hosting with fluctuating resources, bad for consistent high performance because of the overhead in forking processes during traffic spikes.
- pm = static: The gold standard for dedicated VPS resources. The processes are spawned at start-up and stay alive. No forking overhead, predictable memory usage.
For a CoolVDS instance with 4GB RAM dedicated to the web stack, I calculate the pool size based on the average process memory. If top shows your PHP processes average 60MB:
(Total RAM - Reserved for OS/DB) / Process Size
(4096MB - 512MB) / 60MB ≈ 59 processes
Here is the configuration block for a high-performance setup:
; /etc/php-fpm.d/www.conf
[www]
user = nginx
group = nginx
; Use Unix sockets for lower latency than TCP loopback
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
; STATIC management for predictable performance
pm = static
pm.max_children = 50
pm.max_requests = 1000 ; Restart workers every 1000 requests to kill leaks
; Logging slow requests is mandatory for debugging
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
Nginx Configuration for FastCGI
On the Nginx side, we need to ensure the buffer sizes are adequate so we don't write temporary files to disk. Disk I/O is the enemy, even with the enterprise SSD storage we use at CoolVDS.
# /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name example.no;
root /var/www/html;
# Pass PHP scripts to FastCGI server
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Tweak buffers to keep data in RAM
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
}
Pro Tip: Always install APC (Alternative PHP Cache). PHP 5.3/5.4 does not include an opcode cache by default. Without APC, PHP recompiles the script on every single request. Installing php-pecl-apc can increase throughput by 300% instantly.
The Hardware Bottleneck
You can tune software all day, but if your underlying storage has high I/O wait times, your php-fpm processes will pile up waiting for the database or file reads. This is where the "noisy neighbor" effect of standard shared hosting kills you.
In our tests comparing standard SATA HDDs vs the Enterprise SSDs used in CoolVDS, the time to serve a Magento catalog page dropped from 1.2s to 0.3s. When you are targeting customers in Norway, milliseconds matter.
Network Latency and Compliance
Hosting physically in Germany or the Nordics is critical for Norwegian businesses. The latency from Oslo to our datacenter is practically negligible. Furthermore, with the current focus on data privacy under the Personal Data Act (Personopplysningsloven) and Datatilsynet's strict oversight, knowing exactly where your data resides is not optional—it is a legal safeguard.
Final verification
After applying these configs, run a stress test with ab (Apache Bench):
ab -n 1000 -c 50 http://localhost/test.php
If you see dropped connections, check your kernel limits (ulimit). If you see high CPU wait, check your I/O. But do not settle for defaults. In 2012, web performance is a competitive advantage, and your infrastructure should reflect that.
Need a sandbox to test your FPM config? Deploy a CoolVDS SSD instance in 55 seconds and see the difference raw I/O power makes.