Apache vs Nginx: Complete Performance Comparison & Tuning Guide
This comprehensive guide compares Apache and Nginx architectures, benchmarks static and dynamic workloads, explores high‑concurrency testing, and provides detailed tuning steps for both servers along with real‑world case studies and future trends such as HTTP/3 and container deployment.
Apache vs Nginx Performance Comparison and Tuning Guide
Why Web Server Performance Tuning Matters
In today’s fast‑moving internet era, website performance directly impacts user experience and business revenue; a one‑second increase in page load time can reduce conversion rates by 7%.
Chapter 1: Architecture Comparison
1.1 Apache Architecture Deep Dive
Apache HTTP Server uses a modular design based on a process/thread model. Main modes include:
Prefork mode (process mode)
Each process handles one connection
Higher memory overhead but stable
Suitable for CPU‑intensive applications
Worker mode (mixed mode)
Multi‑process + multi‑thread architecture
Higher memory efficiency
Balances performance and stability
Event mode (event‑driven)
Based on asynchronous event handling
Optimized for Keep‑Alive connections
Default mode in Apache 2.4
1.2 Nginx Architecture Deep Dive
Nginx uses a master‑worker multi‑process model with an event‑driven asynchronous non‑blocking architecture:
Master process responsibilities:
Read configuration files
Manage worker processes
Handle signals
Worker process responsibilities:
Handle actual network connections
Each worker can handle thousands of concurrent connections
Based on epoll/kqueue event model
1.3 Architecture Comparison Summary
Feature Apache Nginx
Concurrency Model Process/Thread Event‑driven
Memory Usage Higher Lower
CPU Usage Medium Lower
Concurrent Capacity Medium (1‑2K) High (10K+)
Extensibility Rich modules Limited but efficient modulesChapter 2: Performance Benchmark
2.1 Test Environment Setup
# System environment
OS: CentOS 8.4
CPU: Intel Xeon 4 cores 2.4GHz
Memory: 8GB RAM
Disk: SSD 100GB
# Apache version: 2.4.53
# Nginx version: 1.20.2
# Install Apache
sudo dnf install httpd httpd-tools -y
# Install Nginx
sudo dnf install nginx -y
# Install load testing tools
sudo dnf install httpd-tools wrk -y2.2 Static File Performance Test
# Create test files
dd if=/dev/zero of=/var/www/html/test1k.html bs=1024 count=1
dd if=/dev/zero of=/var/www/html/test10k.html bs=1024 count=10
dd if=/dev/zero of=/var/www/html/test100k.html bs=1024 count=100
# Apache benchmark
ab -n 10000 -c 100 http://localhost/test1k.html
# Nginx benchmark (using wrk)
wrk -t4 -c100 -d30s http://localhost/test1k.htmlTest results show Nginx has a clear advantage for static file serving.
2.3 Dynamic Content Test
<?php
header('Content-Type: text/html; charset=utf-8');
echo "Hello World! " . date('Y-m-d H:i:s');
usleep(1000); // 1ms delay
echo "
Database query completed.";
$result = 0;
for ($i = 0; $i < 1000; $i++) { $result += $i; }
echo "
Calculation result: " . $result;
?>Results:
Server QPS Avg Resp Time Memory CPU%
Apache+PHP 487 205ms 156MB 68%
Nginx+PHP-FPM 612 163ms 124MB 52%2.4 High Concurrency Test
# High concurrency with wrk
wrk -t12 -c1000 -d60s --latency http://localhost/
# Staircase test with ApacheBench
for i in 50 100 200 500 1000 2000; do
echo "Testing with $i concurrent connections"
ab -n 10000 -c $i http://localhost/ > results_$i.txt
sleep 5
doneKey indicators:
Apache limit ~2,000 connections
Nginx limit >10,000 connections
Memory usage: Nginx saves about 40%
CPU efficiency: Nginx leads by ~25%
Chapter 3: Apache Performance Tuning
3.1 MPM Module Optimization
# /etc/httpd/conf/httpd.conf
# Event MPM (recommended)
LoadModule mpm_event_module modules/mod_mpm_event.so
<IfModule mpm_event_module>
ServerLimit 16
MaxRequestWorkers 1000
ThreadsPerChild 64
AsyncRequestWorkerFactor 100
MinSpareThreads 75
MaxSpareThreads 250
ThreadLimit 64
StartServers 3
MaxMemFree 2048
</IfModule>
# Worker MPM (alternative)
<IfModule mpm_worker_module>
StartServers 4
MaxRequestWorkers 1000
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
ServerLimit 40
</IfModule>Key parameters explained: MaxRequestWorkers: maximum concurrent requests ThreadsPerChild: threads per child process ServerLimit: maximum server processes AsyncRequestWorkerFactor: async connection handling factor
3.2 Cache Optimization
# Enable modules
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so
# Static resource cache
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$">
ExpiresActive On
ExpiresDefault "access plus 30 days"
Header append Cache-Control "public, immutable"
</LocationMatch>
# HTML cache
<LocationMatch "\.html$">
ExpiresActive On
ExpiresDefault "access plus 1 hour"
</LocationMatch>
# Gzip compression
<Location />
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
</Location>3.3 Memory and Connection Optimization
# Connection tuning
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# Request size limits
LimitRequestBody 10485760
LimitRequestFields 100
LimitRequestFieldSize 8190
LimitRequestLine 4094
# Preload optimization
<Location />
Header always set Link "</css/main.css>; rel=preload; as=style"
Header always set Link "</js/main.js>; rel=preload; as=script"
</Location>3.4 Security vs Performance
# Hide version info
ServerTokens Prod
ServerSignature Off
# Disable unnecessary modules
#LoadModule autoindex_module modules/mod_autoindex.so
#LoadModule status_module modules/mod_status.so
# Log optimization
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog logs/access_log combinedChapter 4: Nginx Performance Tuning
4.1 Worker Process Optimization
# /etc/nginx/nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
worker_priority -5;
events {
worker_connections 4096;
use epoll;
multi_accept on;
accept_mutex off;
}4.2 Core HTTP Parameters
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
client_header_timeout 60;
client_body_timeout 60;
send_timeout 60;
client_body_buffer_size 16k;
client_header_buffer_size 4k;
large_client_header_buffers 8 16k;
client_max_body_size 50m;
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 120s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}4.3 Gzip Compression
http {
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
gzip_static on;
gzip_proxied any;
}4.4 Cache Strategy
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
# Static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}
# API cache
location /api/ {
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating;
proxy_pass http://backend;
}
# HTML cache
location / {
expires 1h;
add_header Cache-Control "public";
try_files $uri $uri/ @fallback;
}
}
}4.5 Load Balancing and Reverse Proxy
upstream backend {
least_conn;
server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 backup;
keepalive 32;
keepalive_requests 100;
keepalive_timeout 60s;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
proxy_busy_buffers_size 16k;
}
}Chapter 5: System‑Level Optimization
5.1 Kernel Parameter Tuning
# /etc/sysctl.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_tw_buckets = 6000
# File descriptor limits
fs.file-max = 2097152
# Application limits
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
sysctl -p5.2 Monitoring Script Deployment
#!/bin/bash
LOG_FILE="/var/log/webserver_performance.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
LOAD=$(uptime | awk '{print $10,$11,$12}')
MEM_USED=$(free | grep Mem | awk '{printf("%.2f%%", $3/$2 * 100.0)}')
CONNECTIONS=$(ss -s | grep TCP: | awk '{print $4}')
if pgrep nginx > /dev/null; then
NGINX_ACTIVE=$(curl -s http://localhost/nginx_status | head -n 3 | tail -n 1)
echo "$DATE [NGINX] Active: $NGINX_ACTIVE, Load: $LOAD, Memory: $MEM_USED" >> $LOG_FILE
fi
if pgrep httpd > /dev/null; then
APACHE_REQUESTS=$(curl -s http://localhost/server-status?auto | grep "ReqPerSec")
echo "$DATE [APACHE] $APACHE_REQUESTS, Load: $LOAD, Memory: $MEM_USED" >> $LOG_FILE
fiChapter 6: Real‑World Cases
6.1 E‑commerce Site Optimization
Background: 5 million daily PV, peak QPS > 2000.
Apache prefork mode, avg response 850 ms, error rate 3.2 %, CPU 85 %.
Strategy: Switch to Nginx + PHP‑FPM, CDN static assets, configure upstream pool.
upstream php_backend {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
}
server {
listen 80;
root /var/www/html;
index index.php;
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 30d;
return 301 https://cdn.example.com$request_uri;
}
location ~ \.php$ {
fastcgi_pass php_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_cache_key $scheme$request_method$host$request_uri;
fastcgi_cache_valid 200 10m;
fastcgi_cache_use_stale error timeout updating;
}
}Results:
Avg response ↓ to 245 ms (‑71 %).
Error rate ↓ to 0.8 %.
CPU usage ↓ to 45 %.
QPS ↑ to > 4500.
6.2 API Service Optimization
Micro‑service API gateway with rate limiting.
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
listen 80;
limit_req zone=api burst=200 nodelay;
limit_conn conn_limit 20;
location /health { access_log off; return 200 "healthy
"; }
location /api/v1/users {
limit_req zone=api burst=50 nodelay;
proxy_pass http://user_service;
}
location /api/v1/orders {
limit_req zone=api burst=100 nodelay;
proxy_pass http://order_service;
}
}
}Chapter 7: Monitoring and Troubleshooting
7.1 Key Metrics
QPS (Queries Per Second)
Average response time
95 % response time
Error rate
Concurrent connections
CPU/Memory usage
7.2 Monitoring Tools
# Nginx status
server {
listen 8080;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}7.3 Troubleshooting Checklist
System resources – top, iotop, netstat.
Log analysis – slow requests, error codes.
Configuration validation – nginx -t, nginx -T.
Chapter 8: Future Trends
8.1 HTTP/3 and QUIC
server {
listen 443 quic reuseport;
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
add_header Alt‑Svc 'h3-29=":443"; ma=86400';
}8.2 Edge Computing Integration
Web servers increasingly integrate with CDNs and edge nodes for faster content delivery.
8.3 Containerized Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
spec:
containers:
- name: nginx
image: nginx:1.21-alpine
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Conclusion: Choosing the Right Web Server
Apache is suitable when you need rich module support, existing legacy configurations, or .htaccess files. Nginx excels for high‑concurrency, static content, reverse‑proxy, and micro‑service gateways. Continuous monitoring and tuning are essential regardless of the choice.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
