Skip to content
DevOps devops webservers 5 min read

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

FeatureNginxApache
ArchitectureEvent-driven (asynchronous)Process/thread-per-connection
Performance under loadExcellent — handles thousands of idle connections cheaplyGood, but memory grows with each connection
Static file servingVery fast, this is its strengthFast, but slower than Nginx
.htaccess supportNot supported (config is central only)Supported (per-directory overrides)
ModulesCompiled in or loaded at start; fewer dynamic optionsHuge module ecosystem, loaded dynamically
Config styleBlock-based, declarative, lives in /etc/nginxDirective-based, XML-like tags, in /etc/apache2
Reverse proxyBuilt-in, very maturePossible with mod_proxy
Best forHigh-traffic sites, proxies, static contentShared 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 event MPM (Multi-Processing Module) to behave more like Nginx. But out of the box on Ubuntu it uses prefork when 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 situationRecommended server
Serving a static site or single-page appNginx
Reverse proxy in front of Node.js / Java / PythonNginx
High concurrency or limited RAMNginx
Shared hosting where users need .htaccessApache
Legacy app that depends on Apache modulesApache
Classic PHP app with per-folder rulesApache
You want one tool for everything modernNginx

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 .htaccess or module reason to choose Apache.
  • Always test your config before reloading: sudo nginx -t or sudo 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 ufw for exactly the ports you serve, and nothing more.
  • If you must use Apache at scale, switch to the event MPM instead of prefork for better concurrency.
  • Add HTTPS with a free certificate from Certbot regardless of which server you choose.
Last updated June 15, 2026
Was this helpful?