Scaling PHP: Why We Ditched mod_php for PHP-FPM and Nginx
If I see one more server reached MaxClients setting error in a standard Apache error log, I might just pull the plug on the rack myself. It is April 2010, folks. We are building dynamic applications with Magento and Drupal, yet so many systems administrators are still configuring servers like it's 2004.
Here is the reality: The traditional LAMP stack (Linux, Apache, MySQL, PHP) using mod_php is a memory hog. Every time Apache spawns a worker to serve a 1KB static CSS file, it drags the entire PHP interpreter along with it. It’s inefficient, it eats RAM for breakfast, and it is killing your latency.
We recently migrated a high-traffic Norwegian news portal from a standard Apache setup to a LEMP stack (Linux, Nginx, MySQL, PHP-FPM). The result? We dropped memory usage by 60% and tripled the concurrent user capacity without upgrading the hardware. Here is how we did it.
The Bottleneck: Apache mod_php
When using Apache with the Prefork MPM (the default for PHP compatibility), each request is handled by a dedicated process. If you have 2GB of RAM and each Apache child takes 25MB (common with modern frameworks), you cap out at roughly 80 concurrent users. Any request after that queues up. Latency spikes. Users leave.
The Solution: PHP-FPM and Nginx
PHP-FPM (FastCGI Process Manager) separates the web server from the PHP processing. Nginx handles the heavy lifting of connections and static files—which it does asynchronously and incredibly fast—and only passes the actual PHP scripts to the FPM daemon.
Note: As of this writing in Spring 2010, PHP-FPM is technically a patch set for PHP 5.2/5.3, though rumor has it the PHP core team might merge it officially soon. For now, we compile it manually or use trusted repositories like Remi or Dotdeb.
Configuration That Works
Getting this running requires stripping Apache out and dropping in Nginx. Here is a battle-tested snippet for your nginx.conf to pass requests to the FPM backend:
server {
listen 80;
server_name example.no;
root /var/www/public;
# Serve static files directly - Nginx is King here
location ~* \.(jpg|jpeg|gif|png|css|js|ico)$ {
expires 30d;
access_log off;
}
# Pass PHP to FPM
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Tuning the Process Manager
The magic happens in the FPM configuration. You must choose between static and dynamic process management. For dedicated resources, I prefer static to avoid the overhead of spawning children under load.
<value name="pm">static</value>
<value name="max_children">50</value>
If you set this too high, you swap to disk. If too low, you waste CPU. Calculate it: (Total RAM - OS Overhead - DB Buffer) / Average PHP Process Size.
Storage I/O: The Silent Killer
You can tune Nginx all day, but if your disk I/O is slow, your PHP sessions will lock up. PHP writes session data to disk by default. On a busy site, thousands of small read/write operations can choke a standard SATA drive.
This is where hardware choice becomes architectural. At CoolVDS, we have started deploying Enterprise SSD storage across our virtualization clusters. Unlike traditional 15k SAS drives, SSDs provide near-instant access times for small random writes (like session files).
Pro Tip: If you cannot afford SSD hosting yet, move your PHP sessions to Memcached. It eliminates disk I/O for session data entirely.
session.save_handler = memcache
Data Integrity and The "Norwegian" Context
Performance isn't just about raw speed; it's about reliability and compliance. Hosting outside of Norway introduces latency (ping times from Oslo to Amsterdam can add 20-30ms) and legal complexity.
Under the Personal Data Act (Personopplysningsloven), you are responsible for how user data is handled. Hosting locally in Norway ensures you aren't routing sensitive data through jurisdictions with questionable privacy standards. Plus, being physically closer to the NIX (Norwegian Internet Exchange) means your packets have a shorter hop to your users.
Why Virtualization Type Matters
Not all VPSs are created equal. Many budget providers use OpenVZ and oversell resources. If your neighbor on the physical node gets hit with a DDoS attack, your PHP-FPM processes starve for CPU cycles.
This is why CoolVDS relies on Xen virtualization. It provides strict resource isolation. Your RAM is your RAM. When you tune max_children for 50 processes, you know the physical memory is actually there to back it up.
Summary
- Stop using mod_php. It is outdated for high-scale environments.
- Adopt Nginx + PHP-FPM. It handles concurrency efficiently.
- Watch your I/O. Use SSD-backed VPS or offload sessions to memory.
- Host Local. Low latency to Oslo makes the application feel snappier than any code optimization could achieved.
Ready to compile your own LEMP stack without fighting for resources? Spin up a Xen-based instance on CoolVDS. We offer pure SSD options that make PHP-FPM fly.