PHP-FPM vs mod_php: Architecting High-Performance PHP Stacks in 2010
If you are still serving PHP applications using Apache's standard mod_php handler in a high-traffic environment, you are essentially setting money on fire. I've watched too many competent sysadmins throw hardware at a software bottleneck, upgrading to dual-socket Xeons when the real culprit is the bloat of their process model. With the release of PHP 5.3.3 earlier this year, the FastCGI Process Manager (PHP-FPM) finally graduated from a third-party patch to a core feature. It's time to stop making excuses and start optimizing.
The problem with the traditional LAMP stack is memory handling. When you embed the PHP interpreter inside every Apache process via mod_php, your static file requests—images, CSS, JS—are serviced by a heavy process carrying the full weight of the PHP engine. On a busy site targeting users in Oslo or Bergen, where latency is scrutinized, this inefficiency causes swapping, high I/O wait, and eventual downtime.
The Architecture: Nginx + PHP-FPM
The solution gaining massive traction in the enterprise this year is decoupling the web server from the PHP processing. We use Nginx as a lightweight event-driven front end to handle high concurrency and static content, passing only the dynamic PHP requests to a pool of PHP-FPM workers. This is the exact architecture we deploy for high-performance clients on CoolVDS.
Here is the logic: Nginx uses very little memory per connection. It buffers the request and hands it to PHP-FPM over a Unix socket or TCP stack only when necessary. PHP-FPM manages a pool of worker processes that do nothing but execute PHP code. They don't touch your JPEGs.
1. Configuring Nginx for FastCGI
First, you need to tell Nginx how to talk to your PHP backend. Whether you compile Nginx 0.8.x from source or use the repositories, the configuration remains similar. We avoid using if statements for rewrites (Process is evil); instead, use try_files which is stable in recent versions.
server {
listen 80;
server_name example.no;
root /var/www/vhosts/example.no/httpdocs;
index index.php index.html;
# Efficient static file handling
location / {
try_files $uri $uri/ /index.php?$args;
}
# Pass PHP scripts to PHP-FPM
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check if file exists to prevent injection exploits
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Connect via local socket for lower latency than TCP
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
2. Tuning the PHP-FPM Pool
The default php-fpm.conf is rarely optimized for heavy production loads. The most critical directive is the process manager control. You have two main choices: static or dynamic.
For a dedicated VPS Norway instance where you know exactly how much RAM is available, static is often superior. It avoids the overhead of spawning and killing processes during traffic spikes. However, if you are sharing resources (which you shouldn't be if you care about performance), dynamic is safer.
Here is a configuration for a CoolVDS instance with 2GB RAM, reserving memory for the OS and database:
[www]
user = nginx
group = nginx
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
; Use static for predictable performance
pm = static
; Formula: (Total RAM - DB/OS RAM) / Avg Process Size
; Example: (2048MB - 512MB) / 32MB ~= 48 workers
pm.max_children = 48
; Requests per child before respawning (prevents memory leaks)
pm.max_requests = 500
; Slow log is vital for debugging
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
Pro Tip: Always set pm.max_requests. PHP has a history of subtle memory leaks in third-party extensions. Recycling the worker process after 500 or 1000 requests is a safety net that keeps your server stable without manual intervention.
The Mandatory Addition: APC (Alternative PHP Cache)
In 2010, running PHP without an opcode cache is negligence. PHP is an interpreted language; it compiles source code to opcodes on every request. APC caches these opcodes in shared memory.
Install APC via PECL: pecl install apc. Then configure /etc/php.d/apc.ini:
extension=apc.so
apc.enabled=1
apc.shm_segments=1
; Allocate enough memory to cache your entire application codebase
apc.shm_size=64M
; Disable stat checks for maximum I/O reduction in production
; You must restart PHP-FPM to see code changes
apc.stat=0
; Allow APC to store user data (great for caching database results)
apc.user_entries_hint=4096
apc.ttl=7200
apc.user_ttl=7200
Setting apc.stat=0 eliminates the stat() system call for every PHP file inclusion. On a complex Drupal or Magento installation with thousands of included files, this reduces disk I/O significantly.
Hardware Reality: Why Virtualization Matters
Software optimization only goes so far. If the underlying host node is overcommitted, your CPU steal time will skyrocket, and your optimized FPM workers will sit idle waiting for processor cycles. This is common with budget OpenVZ providers.
At CoolVDS, we utilize Xen hypervisors to ensure strict resource isolation. When you define pm.max_children = 48, you need the guarantee that the physical RAM is actually there, not swapped out to a slow disk by the host OS. Furthermore, for Norwegian businesses operating under the Personopplysningsloven (Personal Data Act), data sovereignty is non-negotiable. Hosting on servers physically located in Oslo ensures you meet compliance requirements while benefiting from direct peering at NIX (Norwegian Internet Exchange).
| Metric | Apache (mod_php) | Nginx + PHP-FPM + APC |
|---|---|---|
| Avg Memory per Process | ~45MB | ~25MB |
| Context Switches | High | Low |
| Static File Delivery | Slow (Blocking) | Instant (Non-blocking) |
| Max Request Throughput | ~150 req/sec | ~450 req/sec |
Final Thoughts
Moving to PHP-FPM requires a shift in thinking. You are no longer relying on Apache to handle everything. You are building a distributed system on a single node: Nginx for I/O, PHP-FPM for logic, APC for caching. This stack is the future of PHP hosting.
Don't let legacy configurations dictate your performance. If you are ready to see what a properly tuned stack can do on enterprise-grade hardware with genuine isolation, it is time to upgrade.
Optimize your latency today. Deploy a Xen-based instance on CoolVDS and configure your FPM pool in minutes.