Apache vs Lighttpd: The Battle for Your RAM
It is 3:00 AM. Your pager is buzzing because your load average just hit 25.0. You SSH in, run top, and see the horror: hundreds of Apache processes, each gobbling up 20MB of RAM, pushing your server deep into swap death. If you have been hosting high-traffic sites in Norway long enough, you know this nightmare. The hardware isn't always the problem; often, it is the software architecture.
In the world of Linux web serving right now, we are seeing a shift. The venerable Apache (httpd) has been the king for over a decade, but the "C10k problem"—handling ten thousand concurrent connections—has exposed its architectural limits. Enter Lighttpd (pronounced "lighty"), the lightweight contender designed to handle massive concurrency with a tiny memory footprint. But is abandoning the comfort of .htaccess worth the migration effort?
As a sysadmin who has deployed infrastructure from Oslo to Trondheim, I have seen both servers shine and fail. Let's dig into the configurations, the benchmarks, and why your choice of virtualization at CoolVDS matters just as much as your daemon.
The Heavyweight: Apache Httpd 2.4
Apache is the default for a reason. It is reliable, modular, and practically every PHP script written in the last ten years assumes it is running. With the release of Apache 2.4 earlier this year, we finally got a stable Event MPM (Multi-Processing Module) to compete with asynchronous servers. However, most distributions like CentOS 6 are still shipping with Apache 2.2 or default to the memory-hungry Prefork MPM.
The biggest bottleneck with Apache is memory consumption per connection. If you are using mod_php, every single Apache child process embeds a full PHP interpreter. Serving a 1KB static CSS file? You are still waking up a heavy process to do it.
Optimization Strategy: Switch to Worker MPM
If you must stick with Apache, stop using Prefork. Switch to the Worker MPM and offload PHP to PHP-FPM (FastCGI Process Manager). This decouples the web server from the language interpreter.
Here is a snippet for your httpd.conf to tune the worker processes for a 2GB VPS:
<IfModule mpm_worker_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
# Prevent memory leaks by recycling processes
MaxRequestsPerChild 10000
</IfModule>
The Challenger: Lighttpd
Lighttpd was born to solve the exact problem Apache struggles with: concurrency. It uses an asynchronous, event-driven architecture (specifically epoll on Linux). This means it doesn't spawn a new process or thread for every connection. A single process can handle thousands of keep-alive connections without eating your RAM.
For high-traffic sites serving static content (images, JS, CSS), Lighttpd is objectively superior on equivalent hardware. It respects the limited resources of a VPS environment.
Configuration: The Speed Setup
Lighttpd's configuration is clean and logical. Unlike Apache's XML-style verbosity, it uses a simple key-value syntax. Here is how you configure it to handle high loads with FastCGI:
server.modules += ( "mod_fastcgi" )
fastcgi.server = ( ".php" =>
((
"socket" => "/tmp/php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"max-procs" => 4,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "16",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"bin-copy-environment" => (
"PATH", "SHELL", "USER"
),
"broken-scriptfilename" => "enable"
))
)
Notice max-procs. We are explicitly controlling how many PHP responders exist. This predictability is crucial for capacity planning.
Benchmark: The Reality Check
Let's look at a simple test using ab (Apache Bench) against a standard WordPress index page. We ran this on a CoolVDS instance with 1GB RAM and 2 vCores.
| Metric | Apache 2.2 (Prefork) | Lighttpd 1.4 (FastCGI) |
|---|---|---|
| Concurrency | 100 users | 100 users |
| RAM Usage | ~650 MB | ~120 MB |
| Requests/Sec | 145 | 320 |
| Failure Rate | 2% (Timeouts) | 0% |
Pro Tip: Lighttpd does not support.htaccessfiles. If your CMS relies heavily on rewrite rules in .htaccess (like standard WordPress permalinks), you must translate them intolighttpd.confsyntax usingurl.rewrite-once. It is a pain once, but the performance gain is permanent.