Comparing the best web servers: Caddy, Apache, and Nginx
Tags: webdev, nginx, programming, productivity
Published: 2021-10-13 16:38:50

**Written by [Ayooluwa Isaiah](https://blog.logrocket.com/author/ayooluwaisaiah/)** ✏️

A web server is a piece of software that accepts a network request from a user agent, typically a web browser, and returns either the appropriate response for the request or an error message. Two dominant solutions for HTTP servers today are Apache and Nginx. However, a new player in the space, Caddy Web Server, is gaining traction for its ease of use.

In this article, we’ll examine each web server, comparing the performance, customizability, and architecture of each. By the end of this tutorial, you should be familiar with the strengths of each web server and have a better grasp of which one is best suited for your project.

Let’s get started!

## Apache HTTP Server

The [Apache HTTP Server](https://httpd.apache.org), maintained by the Apache Software Foundation, was released in 1995, quickly becoming the world’s favorite web server. Most often used as part of the LAMP stack, Linux, Apache, MySQL, and PHP, Apache is available for both Unix and Windows operating systems.

### Performance

Open sourced and written in C, Apache is based on a modular architecture that allows a system administrator to select what modules to apply either during compilation or at runtime, easily configuring how the server should operate. As a result, Apache caters to a wide range of use cases, from serving dynamic content to acting as a load balancer for [supported protocols like HTTP and WebSockets](https://blog.logrocket.com/websockets-tutorial-how-to-go-real-time-with-node-and-react-8e4693fbf843/).

Apache’s core functionalities include binding to ports on a machine and accepting and processing requests. However, these tasks are isolated by default through a set of Multi-Processing Modules (MPMs) that are included with the software package.

The MPM architecture offers more options for customization depending on the needs of a particular site and the machine’s capabilities. For example, worker or event MPMs can replace the older prefork MPM, which uses one thread per connection and doesn't scale well when concurrency is required.

In addition to the modules that are shipped as part of the server distribution, there is an [abundance of third-party modules for Apache](https://httpd.apache.org/modules/) that you can use to extend its functionality.

### Configuration

You can find Apache's main configuration in a `.conf` file: `/etc/apache2/apache2.conf` on Debian-based Linux distributions and `/etc/httpd/httpd.conf` on Fedora and Red Hat Enterprise Linux.

However, to specify an alternate configuration file and achieve a desired behavior, you can use the `-f` flag and any of the [available directives](https://httpd.apache.org/docs/2.4/mod/directives.html). Divide the server configuration into several `.conf` files and add them using the `Include` directive. Keep in mind that Apache may recognize changes to the main configuration file only after restarting.

You can also change server configuration at the directory level using an [`.htaccess` file](https://httpd.apache.org/docs/2.4/howto/htaccess.html#when), allowing you to customize behavior for individual websites without changing the main configuration. However, `.htaccess` files can increase TTFB and CPU usage, degrading performance. When possible, you should avoid using `.htaccess` files, and you can disable them altogether by setting the `AllowOverride` directive to `none`.

## Nginx

With origins tracing back to the [C10K problem](https://www.nginx.com/blog/maximizing-python-performance-with-nginx-parti-web-serving-and-caching/), which refers to a web server’s inability to support more than 10,000 concurrent users, [Nginx](https://nginx.org) was developed with performance in mind. One of its original goals focused on speed, an area in which Apache was believed to be lacking.

First appearing publicly in 2004 as an open source software under the 2-clause BSD license, Nginx expanded in 2011 with a commercial variant for the enterprise called Nginx Plus.

Nginx is [currently being utilized on over 40 percent](https://w3techs.com/technologies/overview/web_server) of the top 10,000 websites. When you consider that Cloudflare Server also utilizes Nginx under the hood for content delivery, the figure is even higher:

![Web Server Usage Statistics W3 Tech](https://blog.logrocket.com/wp-content/uploads/2021/10/web-server-usage-statistics-w3-tech.png)

### Configuration

The default configuration, which is recommended, involves setting the `worker_processes` directive to `auto`. To utilize hardware resources efficiently, one worker process is created per CPU.

On a Unix operating system, the configuration files for Nginx are located in the `/etc/nginx/` directory with `nginx.conf` as the main configuration file. Nginx uses directives for its configuration, which are grouped into blocks or contexts. A skeleton of the configuration file is shown below:

```coffeescript
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
  . . .
}

http {
  . . .
}
```

### Performance

When high performance and scalability are critical requirements, Nginx is frequently the go-to web server. Nginx uses an asynchronous, event-driven, and non-blocking architecture. It follows a multi-process model in which one master process creates a number of worker processes for handling all network events:

```shell
$ ps aux -P | grep nginx
root     19199  0.0  0.0  55284  1484 ?        Ss   13:02   0:00 nginx: master process /usr/sbin/nginx
www-data 19200  0.0  0.0  55848  5140 ?        S    13:02   0:00 nginx: worker process
www-data 19201  0.0  0.0  55848  5140 ?        S    13:02   0:00 nginx: worker process
www-data 19202  0.0  0.0  55848  5140 ?        S    13:02   0:00 nginx: worker process
www-data 19203  0.0  0.0  55848  5140 ?        S    13:02   0:00 nginx: worker process
```

The master process controls the workers’ behaviors and carries out privileged operations like binding to network ports and applying configuration, allowing Nginx to support thousands of incoming network connections per worker process. Instead of creating new threads or processes for each connection, you only need a new file descriptor and a small amount of additional memory.

## Caddy

[Caddy](https://caddyserver.com/) is an open source web server platform designed to be simple, easy to use, and secure. Written in Go with zero dependencies, Caddy is easy to download and runs on almost every platform that Go compiles on.

By default, Caddy comes with support for automatic HTTPS by provisioning and renewing certificates through [Let's Encrypt](https://letsencrypt.org). Of the three web servers we’ve reviewed, Caddy is the only to provide these features out of the box, and it also comes with automatic redirection of HTTP traffic to HTTPS.

In comparison to Apache and Nginx, Caddy's configuration files are much smaller. Additionally, Caddy runs on TLS 1.3, the newest standard in transport security.

Installing Caddy is quite straightforward. Simply download the static binary for your preferred platform on [GitHub](https://github.com/caddyserver/caddy/releases) or follow the instructions on the [installation document](https://github.com/caddyserver/caddy/releases). To launch the Caddy server daemon, run `caddy run` in the terminal. However, nothing will happen without a configuration file.

### Configuration

Caddy uses JSON for its configuration but also supports several configuration adapters. The standard for setting up configuration is through a Caddyfile. Here's a simple "Hello World" configuration, which binds to `port 3000`:

```JSON
:3000 {
    respond "Hello, world!"
}
```

For the changes to take effect, you’ll need to stop the server by pressing `Ctrl+C` and restarting it with `caddy run`. Alternately, you can apply the new configuration to a running server by executing `caddy reload` in a separate terminal. The latter approach is preferable to avoid downtime.

At this point, accessing `http://localhost:3000` in your browser or through `curl` should produce the expected "Hello, world!" message:

```JSON
$ curl http://localhost:3000
Hello, world!
```

Caddy provides the following directives:

*   `file_server`: implements a static file server
*   `php_fastcgi`: proxies requests to a PHP FastCGI
*   `reverse_proxy`: directs incoming traffic to one or more backends with load balancing, health checks, and automatic retries

### Performance

In terms of performance, Caddy has been shown to be [competitive with Apache but behind Nginx](https://github.com/centminmod/centminmod-caddy-v2#caddy-vs-centmin-mod-nginx-http2-https-benchmarks) both in terms of requests handled per second and stability under load.

If Nginx is being used for performance optimization,  it may not be possible to replace it with Caddy without observing some degradation in performance. Another possible downside to Caddy is that it [currently has a small market share](https://w3techs.com/technologies/overview/web_server), possibly limiting resources for education and troubleshooting:

![W3 Web Server Popularity By Ranking](https://blog.logrocket.com/wp-content/uploads/2021/10/w3-web-server-popularity-by-ranking.png)

## Conclusion

In this article, we discussed some of the key traits of Caddy, Apache, and Nginx to help you choose the web server that best suits your project’s needs.

If your primary concern is performance, or you plan to serve a large amount of static content, Nginx is likely your best option. While Caddy is easy to configure and performant for most use cases, if you need flexibility and customization, Apache is your best bet.

Keep in mind that you can also combine any two web servers for a great result. For example, you can serve static files with Nginx and process dynamic requests with Apache or Caddy. Thanks for reading, and happy coding!



---

## [LogRocket](https://logrocket.com/signup/): Full visibility into your web apps

[![LogRocket Dashboard Free Trial Banner](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://logrocket.com/signup/)

[LogRocket](https://logrocket.com/signup/) is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

[Try it for free](https://logrocket.com/signup/).