Nginx vs Apache
Nginx and Apache are the two most popular web servers on the internet. A web server is the program that listens for requests from browsers and sends back web pages, images, or data from your application. Both can serve websites, act as a reverse proxy (a server that sits in front of your app and forwards browser requests to it), and handle HTTPS. The hard part is knowing which one to pick — so this page compares them honestly and gives you a clear recommendation.
The quick answer
For most modern setups in 2026, use Nginx. It is faster under heavy traffic, uses less memory, and is the standard choice for serving static files and proxying to apps like Node.js, Python, or Java. Pick Apache when you specifically need .htaccess files (per-directory config that non-admins can edit) or rely on Apache-only modules. If you are unsure, start with Nginx.
Side-by-side comparison
| Feature | Nginx | Apache |
|---|---|---|
| Architecture | Event-driven (asynchronous) | Process/thread-per-connection |
| Performance under load | Excellent — handles thousands of idle connections cheaply | Good, but memory grows with each connection |
| Static file serving | Very fast, this is its strength | Fast, but slower than Nginx |
.htaccess support | Not supported (config is central only) | Supported (per-directory overrides) |
| Modules | Compiled in or loaded at start; fewer dynamic options | Huge module ecosystem, loaded dynamically |
| Config style | Block-based, declarative, lives in /etc/nginx | Directive-based, XML-like tags, in /etc/apache2 |
| Reverse proxy | Built-in, very mature | Possible with mod_proxy |
| Best for | High-traffic sites, proxies, static content | Shared hosting, legacy apps, .htaccess needs |
How they handle traffic: the core difference
This is the single most important thing to understand. The two servers use completely different models to deal with many users at once.
Apache’s process model
Apache traditionally creates a new process or thread for each connection (a connection is one open line between a browser and the server). With its common prefork setup, every visitor gets a dedicated worker. This is simple and very compatible, but each worker uses memory even while it sits idle waiting for the user. If 5,000 people connect at once, Apache may need 5,000 workers, and memory can run out. This is sometimes called the “C10k problem” (handling 10,000 concurrent connections).
Apache can be tuned with the
eventMPM (Multi-Processing Module) to behave more like Nginx. But out of the box on Ubuntu it usespreforkwhen PHP is involved, which is the memory-hungry mode.
Nginx’s event-driven model
Nginx uses a small fixed number of worker processes — usually one per CPU core. Each worker handles thousands of connections at the same time using an event loop (a single process that watches many connections and only does work when one of them actually has data ready). Because idle connections cost almost nothing, Nginx stays fast and light even under huge load. This is why it powers so many of the busiest sites in the world.
When to care: if you expect bursts of traffic, many slow mobile clients, or lots of concurrent connections, the Nginx model wins clearly.
Trying both on Ubuntu
You can install either server on Ubuntu 22.04 or 24.04 LTS in seconds. They both listen on port 80 by default, so do not run them at the same time on the same port.
Install Nginx:
sudo apt update
sudo apt install -y nginx
sudo systemctl status nginx
Output:
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-06-15 09:12:04 UTC; 3s ago
Install Apache (stop Nginx first if it is running, since both use port 80):
sudo systemctl stop nginx
sudo apt install -y apache2
sudo systemctl status apache2
Output:
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-06-15 09:13:21 UTC; 2s ago
Allow web traffic through the firewall (ufw is Ubuntu’s simple firewall tool):
sudo ufw allow 'Nginx Full'
sudo ufw allow 'Apache Full'
sudo ufw status
Output:
Status: active
To Action From
-- ------ ----
Nginx Full ALLOW Anywhere
Apache Full ALLOW Anywhere
Config style compared
The configuration files look quite different. Nginx uses clean curly-brace blocks. Here is a minimal Nginx site that serves files from a folder:
server {
listen 80;
server_name example.com;
root /var/www/example;
location / {
try_files $uri $uri/ =404;
}
}
Apache uses tag-style directives. The same idea in Apache looks like this:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example
<Directory /var/www/example>
Require all granted
</Directory>
</VirtualHost>
Notice that Nginx keeps all config central. Apache also lets you drop a .htaccess file inside any folder to override settings without touching the main config — handy on shared hosting, but it costs a small performance hit because Apache checks for those files on every request.
When to use which
| Your situation | Recommended server |
|---|---|
| Serving a static site or single-page app | Nginx |
| Reverse proxy in front of Node.js / Java / Python | Nginx |
| High concurrency or limited RAM | Nginx |
Shared hosting where users need .htaccess | Apache |
| Legacy app that depends on Apache modules | Apache |
| Classic PHP app with per-folder rules | Apache |
| You want one tool for everything modern | Nginx |
Do not run Nginx and Apache on the same port at the same time — one will fail to start with an “Address already in use” error. A common advanced pattern is putting Nginx in front of Apache (Nginx handles static files and HTTPS, Apache runs the app), which gets you the best of both.
Best practices
- Default to Nginx for new projects unless you have a concrete
.htaccessor module reason to choose Apache. - Always test your config before reloading:
sudo nginx -torsudo apache2ctl configtest. - Reload instead of restart to apply changes without dropping connections:
sudo systemctl reload nginx. - Keep only one server bound to port 80/443 to avoid startup conflicts.
- Open the firewall with
ufwfor exactly the ports you serve, and nothing more. - If you must use Apache at scale, switch to the
eventMPM instead ofpreforkfor better concurrency. - Add HTTPS with a free certificate from Certbot regardless of which server you choose.