The C10k Problem is Real, and Apache isn't the Answer
I watched a server die yesterday. It wasn't a hardware failure, and it wasn't a power outage at the datacenter in Oslo. It was a marketing campaign. A client sent out a newsletter, traffic spiked, and their Apache serverâconfigured with the standard Prefork MPMâspawned hundreds of child processes until the machine swapped itself to death. The site was down for two hours. The culprit? RAM exhaustion.
If you are still serving static assets (images, CSS, JS) directly through Apache in 2011, you are burning money. Apache is fantastic for dynamic content (PHP/Python), but it is heavy. Creating a full thread for a 4KB icon file is architectural suicide.
The solution is not "buy more RAM." The solution is Nginx. By placing Nginx in front of Apache as a reverse proxy, you act as a bouncer. Nginx handles the high-volume static connections asynchronously (thanks to its event-driven architecture), and only hands off the heavy lifting to Apache when absolutely necessary.
The Architecture: The Best of Both Worlds
We aren't throwing Apache away. Most of you are running heavy CMS setups like Drupal, WordPress, or Magento that rely on .htaccess files. Porting those rewrite rules to Nginx logic is a nightmare you don't need right now.
Instead, we use this topology:
- Port 80 (Public): Nginx listens here. It serves images, styles, and scripts instantly.
- Port 8080 (Local): Apache listens here, bound to
127.0.0.1. It processes PHP files.
This setup reduces RAM usage significantly because Nginx has a tiny memory footprint.
Implementation on CentOS 5/6
Let's get our hands dirty. First, you need the EPEL repository because the standard repos are woefully behind. Once you have Nginx 1.0.x installed, here is the configuration strategy.
1. Configure Apache
Edit your httpd.conf. You need to change the Listen port so it doesn't conflict with Nginx.
# /etc/httpd/conf/httpd.conf
Listen 127.0.0.1:8080
ServerName localhost:8080Pro Tip: Install mod_rpaf. Without it, Apache will see all incoming requests as coming from 127.0.0.1 (Nginx) rather than the real user IP. This messes up your logs and security plugins.
2. Configure Nginx
Here is a battle-tested server block. I've stripped out the fluff.
server {
listen 80;
server_name example.no www.example.no;
root /var/www/vhosts/example.no/httpdocs;
# Serve static files directly
location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
access_log off;
log_not_found off;
expires 30d;
}
# Pass everything else to Apache
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Timeouts are critical for slow PHP scripts
proxy_connect_timeout 60;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}Reload both services. Your RAM usage should drop like a stone.
The "Hardware" Bottleneck
Software optimization only gets you so far. If your underlying storage subsystem is garbage, your database (MySQL) will still choke on I/O wait times. This is the dirty secret of the hosting industry.
Many providers oversell their nodes, stacking 50 VPS customers on a single spinning hard drive array. When your neighbor runs a backup, your site slows down. At CoolVDS, we have moved aggressively to SSD storage for our high-performance tiers. In 2011, SSDs are expensive, yes, but the IOPS (Input/Output Operations Per Second) difference is logarithmic. We are talking about 100x faster random reads compared to 15k SAS drives.
Datatilsynet Compliance Note: Hosting in Norway isn't just about speed; it's about the law. With the strict enforcement of the Personal Data Act (Personopplysningsloven), keeping your data within Norwegian borders at a facility connected to NIX (Norwegian Internet Exchange) ensures you aren't accidentally routing sensitive customer data through jurisdictions with weaker privacy protections.
Comparison: Standalone Apache vs. Nginx Proxy
| Metric | Apache Only | Nginx Proxy + Apache |
|---|---|---|
| Max Concurrent Users | ~250 (on 1GB RAM) | ~3,000+ |
| Memory per Connection | High (~15-20MB) | Low (~2MB for Nginx) |
| Static File Speed | Slow (Blocking) | Instant (Non-blocking) |
Summary
Don't wait for your site to crash during the Christmas rush. Implementing Nginx as a reverse proxy is the single most effective change you can make to your stack today without rewriting code.
However, if you apply these configs and your server load is still high, check your I/O wait (top command, look at wa). If it's over 10%, your host is the problem, not your config. Deploy a KVM instance on CoolVDS todayâwe use pure SSD storage and guarantee your resources so you never have to worry about noisy neighbors again.