Nginx and Apache are the two most popular web servers in the world, powering over 60% of all websites combined. If you are setting up a web server, you will inevitably face the question: which one should you use?
The short answer: Nginx is better for most modern use cases. The longer answer depends on your specific needs. This guide compares both in detail so you can make an informed choice.
Market Share
As of 2026:
| Server | Market Share | Notable Users |
|---|---|---|
| Nginx | ~34% | Netflix, Cloudflare, WordPress.com, Dropbox |
| Apache | ~30% | Apple, Adobe, PayPal, many shared hosts |
| Cloudflare | ~21% | Acts as reverse proxy in front of other servers |
| Others | ~15% | Caddy, LiteSpeed, IIS, etc. |
Nginx has been the most popular web server since 2019, overtaking Apache after a decade of growth.
Architecture: The Fundamental Difference
This is the core distinction that drives every other difference.
Apache: Process/Thread Per Connection
Apache creates a new process or thread for each incoming connection. With the default prefork MPM (Multi-Processing Module), each request gets its own process:
Client 1 → Process 1
Client 2 → Process 2
Client 3 → Process 3
...
Client 1000 → Process 1000
Each process uses memory (typically 5-10 MB). With 1,000 concurrent connections, Apache uses 5-10 GB of RAM just for connection handling.
Worker MPM improves this by using threads instead of processes (less memory per connection), and Event MPM adds non-blocking I/O for keepalive connections. But the fundamental model is still one thread per active request.
Nginx: Event-Driven, Non-Blocking
Nginx uses a single-threaded event loop (one per CPU core). One worker process handles thousands of connections simultaneously:
Client 1 ──┐
Client 2 ──┤
Client 3 ──┼── Worker Process 1 (event loop)
... │
Client 5000┘
Client 5001──┐
Client 5002──┼── Worker Process 2 (event loop)
... │
Client 10000─┘
Each worker process uses a fixed amount of memory regardless of how many connections it handles. Nginx can handle 10,000+ concurrent connections with just 2-3 MB per worker.
This is why Nginx uses less memory and handles more concurrent connections.
Performance Comparison
Static Files
Nginx is significantly faster at serving static files (HTML, CSS, JS, images):
| Metric | Nginx | Apache |
|---|---|---|
| Requests/sec (static) | ~25,000 | ~10,000 |
| Memory per 10K connections | ~30 MB | ~500 MB+ |
| Latency (static) | Lower | Higher |
Nginx was literally designed for this — its event-driven architecture makes it excellent at serving files from disk without blocking.
Dynamic Content (PHP, Python, etc.)
For dynamic content, both perform similarly because the bottleneck is the application (PHP, Python, Ruby), not the web server:
| Setup | Performance |
|---|---|
| Apache + mod_php | Good (PHP runs inside Apache) |
| Nginx + PHP-FPM | Good (PHP runs as separate process) |
| Apache + PHP-FPM | Good (same as Nginx approach) |
The difference is negligible because Apache/Nginx is just passing the request to PHP — the PHP execution time dominates.
Reverse Proxy
Nginx is the standard choice for reverse proxying:
# Nginx reverse proxy — clean and simple
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Apache can do it too with mod_proxy, but Nginx's event-driven architecture makes it handle more concurrent proxy connections with less overhead.
SSL/TLS
Both handle SSL well, but Nginx's lower memory footprint means it handles more concurrent HTTPS connections. Both support TLS 1.3, HTTP/2, and OCSP stapling.
Test your SSL configuration with our SSL Server Test.
Configuration
Nginx Configuration
Nginx uses a declarative, block-based config:
server {
listen 443 ssl http2;
server_name www.samnet.dev;
root /var/www/html;
ssl_certificate /etc/letsencrypt/live/samnet.dev/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/samnet.dev/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
location ~* \.(jpg|css|js)$ {
expires 30d;
}
}
Pros: Fast to parse, centralized, predictable Cons: No per-directory overrides (no .htaccess), requires reload for changes
Apache Configuration
Apache uses a similar structure but with more options:
<VirtualHost *:443>
ServerName www.samnet.dev
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/samnet.dev/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/samnet.dev/privkey.pem
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
ProxyPass /api/ http://127.0.0.1:3000/
ProxyPassReverse /api/ http://127.0.0.1:3000/
<FilesMatch "\.(jpg|css|js)$">
ExpiresActive On
ExpiresDefault "access plus 30 days"
</FilesMatch>
</VirtualHost>
Pros: .htaccess for per-directory overrides, more modules available
Cons: .htaccess causes a performance hit (Apache checks for it on every request)
The .htaccess Question
Apache's .htaccess files let you override server config per directory without restarting Apache. This is why shared hosting uses Apache — each customer can configure their own directory.
Nginx has no equivalent. All configuration is centralized and requires a reload:
sudo nginx -t && sudo systemctl reload nginx
For your own server, this is actually better — centralized config is easier to manage and faster to serve. .htaccess is only necessary in shared hosting environments where users cannot edit the main config.
When to Use Nginx
- Reverse proxy in front of application servers (Node.js, Python, Go, etc.)
- Static file serving — images, CSS, JS, HTML
- High traffic — 10,000+ concurrent connections
- Load balancing across multiple backend servers
- Low memory environments — VPS with limited RAM
- Microservices — routing traffic to different services
- CDN/caching layer — Nginx's caching is excellent
- Your own server where you control the config
When to Use Apache
- Shared hosting — .htaccess support is essential
- WordPress (on shared hosting) — many plugins depend on .htaccess
- Legacy PHP apps — mod_php is deeply integrated
- Per-directory configuration needed by multiple users
- Specific Apache modules with no Nginx equivalent
The Common Pattern: Both
Many production setups use both:
Internet → Nginx (reverse proxy, SSL, static files, caching)
└→ Apache (dynamic PHP content)
Or more commonly:
Internet → Nginx (reverse proxy, SSL, static files)
├→ Node.js app (port 3000)
├→ Python app (port 8000)
└→ PHP-FPM (socket)
Nginx handles the internet-facing connections, SSL termination, and static files. Backend applications handle the dynamic logic. This gives you the best of both worlds.
Quick Decision Guide
| Question | Choose |
|---|---|
| Setting up a new server? | Nginx |
| Shared hosting? | Apache (probably your only choice) |
| Reverse proxy for apps? | Nginx |
| WordPress on your own VPS? | Nginx + PHP-FPM |
| Legacy app requires .htaccess? | Apache |
| High traffic, limited RAM? | Nginx |
| Need both? | Nginx in front, Apache behind |
Test Your Setup
- SSL Server Test — analyze your TLS configuration
- HTTPS Redirect Tester — verify HTTP→HTTPS redirects and HSTS
- Port Scanner — check which ports your server exposes
- Global Latency Test — measure your server's response time worldwide