Apache and Nginx are the two most widely deployed open source web servers, and both are production grade, secure and well maintained. They differ in how they handle connections, how they are configured and what they are best at, and those differences matter more than any headline benchmark. This guide compares them side by side with equivalent configuration examples for Ubuntu 24.04, then gives concrete recommendations for common workloads.

Prerequisites

This is a conceptual guide, but if you want to try the examples you need:

  • A server running Ubuntu 24.04 LTS, such as a CubePath VPS, with a non-root sudo user.
  • Basic familiarity with the Linux command line and HTTP.

Quick comparison

AspectApache HTTP ServerNginx
Connection modelProcesses or threads via an MPM (event by default on Ubuntu)Small number of single-threaded, event-driven workers
Static filesFastVery fast, with lower memory per connection
PHPPHP-FPM (recommended) or embedded mod_phpPHP-FPM only
Per-directory configYes, .htaccessNo, all config lives in server files
ModulesLoaded at runtime with a2enmodCompiled in; dynamic modules exist but are fewer
Reverse proxy and load balancingYes (mod_proxy, mod_proxy_balancer)Yes, a core strength
Config reloadGraceful (systemctl reload apache2)Graceful (systemctl reload nginx)
Ubuntu 24.04 packageapache2 (2.4.58)nginx (1.24.0)

Architecture

Apache: Multi-Processing Modules

Apache delegates connection handling to a Multi-Processing Module (MPM):

  • prefork: one single-threaded process per connection. Robust but memory hungry. Required only by non-thread-safe modules such as mod_php.
  • worker: several processes, each with many threads, one thread per connection.
  • event: like worker, but idle keep-alive connections are handed to a listener thread instead of occupying a worker thread. This is Ubuntu's default.

Check which one is active:

apache2ctl -V | grep -i mpm
Server MPM:     event

With event, modern Apache handles thousands of concurrent connections comfortably. The old reputation for high memory use mostly comes from prefork combined with mod_php, where every connection carries a full PHP interpreter.

Nginx: event-driven workers

Nginx starts one master process and a few worker processes, typically one per CPU core (worker_processes auto;). Each worker runs a non-blocking event loop and multiplexes thousands of connections. Memory use stays nearly flat as connections grow, which makes Nginx well suited to many slow or idle clients, long polling, WebSockets and serving static assets at high concurrency.

The trade-off is that Nginx never runs application code inside itself. Anything dynamic is passed to another process over FastCGI, uWSGI or HTTP.

Configuration style

Both servers use one file per site on Ubuntu. Apache calls them virtual hosts, Nginx calls them server blocks. Here is the same static site in both.

Apache, /etc/apache2/sites-available/your_domain.conf:

<VirtualHost *:80>
    ServerName your_domain
    DocumentRoot /var/www/your_domain/html

    <Directory /var/www/your_domain/html>
        Options -Indexes
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

Nginx, /etc/nginx/sites-available/your_domain:

server {
    listen 80;
    server_name your_domain;
    root /var/www/your_domain/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Apache's configuration is directory centric (<Directory>, <Files>), while Nginx's is URI centric (location). Both test and reload the same way:

sudo apache2ctl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx

.htaccess files

The biggest practical difference is .htaccess. With AllowOverride All, Apache reads .htaccess files in every directory on the request path, on every request. That costs some performance but lets users change rewrites and access rules without touching the server configuration or reloading. Shared hosting, WordPress plugins and many PHP applications rely on it.

Nginx has no equivalent. Rules must be translated into the server block and applied with a reload. For example, a typical front controller rule in .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]

becomes this in Nginx:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

If you control the server and deploy through a pipeline, the lack of .htaccess is rarely a problem. If end users or plugins need to change rules themselves, it is a strong reason to stay on Apache.

Running PHP

For both servers the recommended setup on Ubuntu 24.04 is PHP-FPM, which runs PHP in its own pool of processes:

sudo apt install php8.3-fpm

Apache connects to it with mod_proxy_fcgi. Ubuntu ships a ready-made snippet:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl reload apache2

Nginx needs a location in the server block, using the snippet included in the package:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

With PHP-FPM, both servers perform similarly for PHP applications, because the time is spent in PHP and the database, not in the web server. Avoid libapache2-mod-php on new installs: it forces Apache back to the prefork MPM.

Reverse proxying and load balancing

Both can sit in front of Node.js, Python or Go applications. In Nginx:

location / {
    proxy_pass http://127.0.0.1:3000;
    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_set_header X-Forwarded-Proto $scheme;
}

In Apache, after sudo a2enmod proxy proxy_http headers:

ProxyPreserveHost On
ProxyPass        / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
RequestHeader set X-Forwarded-Proto "http"

Nginx's proxy module is more commonly used for this role, has built-in response caching (proxy_cache), upstream groups with several balancing methods and handles WebSockets with two extra headers. Apache can do the same with mod_proxy_balancer, mod_cache and mod_proxy_wstunnel, but Nginx is the more common choice as a dedicated reverse proxy.

Security

Neither server is inherently more secure; both receive prompt security updates from Ubuntu. The practical differences are:

  • Attack surface. Apache's rich module set is flexible but means more code loaded if you do not prune it. List active modules with apache2ctl -M and disable what you do not use with a2dismod. Nginx's default build is smaller.
  • .htaccess. Convenient, but a writable .htaccess in a compromised web directory can change server behavior. Set AllowOverride None when you do not need it.
  • Rate limiting. Nginx has built-in request and connection limits (limit_req, limit_conn). Apache relies on third-party modules such as mod_evasive or on a firewall.
  • Hiding versions. Apache uses ServerTokens Prod and ServerSignature Off; Nginx uses server_tokens off;.

Measuring on your own workload

Published benchmarks rarely reflect your application. If performance is the deciding factor, test both with your real site. ab from apache2-utils is enough for a first comparison:

sudo apt install apache2-utils
ab -n 5000 -c 100 http://your_server_ip/

Look at Requests per second, Time per request and the Failed requests line, and watch memory with free -m during the run. Run the benchmark from a different machine than the server, otherwise the load generator competes for the same CPU.

Using both together

A common architecture puts Nginx on ports 80 and 443 as the TLS terminator and static file server, and Apache on a local port (for example 127.0.0.1:8080) running an application that depends on .htaccess. Nginx proxies dynamic requests to Apache. This combines Nginx's efficient connection handling with Apache's compatibility, at the cost of running and monitoring two services. When Apache sits behind a proxy, enable mod_remoteip so logs show the real client IP instead of 127.0.0.1.

Which one should you choose?

Choose Apache when:

  • You run WordPress, Drupal or other PHP software whose plugins write .htaccess rules.
  • Several users or clients need to manage their own site rules without server access.
  • You rely on Apache-specific modules, for example mod_security rule sets tuned for Apache or specific authentication modules.
  • Your team already knows Apache well; a well-tuned Apache with event and PHP-FPM is fast enough for most sites.

Choose Nginx when:

  • You mostly serve static files, single-page applications or downloads.
  • You need a reverse proxy, load balancer or TLS terminator in front of application servers.
  • You expect many concurrent or long-lived connections (WebSockets, streaming, APIs with keep-alive).
  • The server has limited memory.

If you are starting a new project with no .htaccess dependency, Nginx is usually the simpler default. If you are migrating existing PHP sites that depend on .htaccess, Apache avoids a rewrite of every rule.

Conclusion

Apache offers flexibility, runtime modules and per-directory configuration; Nginx offers a lean event-driven model that excels at static content and proxying. With the event MPM and PHP-FPM, the performance gap for typical PHP sites is small, so let configuration needs and your team's experience drive the decision. To get started, follow the guide to install and configure either Apache or Nginx on Ubuntu 24.04, then set up virtual hosts or server blocks for your domains.