A History and Brief Comparison of NGINX and Apache

I am by no means a web server expert, but I have quite a bit of experience configuring a local server for web development and experimentation purposes.

When it comes to selecting a Linux-based web server upon which to serve your web assets, it often comes down to a single question: "Should I use NGINX or Apache?" Both are excellent web servers, and, with a little configuration, they can both generally do the same job as the other. NGINX will likely always have a slight advantage on a high-volume site with high concurrency, but a properly tuned Apache server can likely get the job done as well.

So the general answer is that it does not matter, especially for local development. If your production website runs on a specific server, I recommend using that one. To get to PHP development as fast as possible, I recommend Apache. If you want to use .htaccess files for per-directory configuration, use Apache. For local development, where requirements might change completely over the years or project to project, I recommend Apache. To have the highest concurrency -- or thousands of people using your site at once -- I recommend NGINX. The good news is, if you want the best of both worlds, you can use both! If you're interested in what each of these servers really stands for, let's go over some history.

Apache

Apache came before NGINX. It was first written in a world where the web was new, and setting up a server was no trivial task. Its focus was primarily on being a jack-of-all-trades. The impression I've gotten from Apache over the years has always been similar to that of the famous "5-minute install" from WordPress. Installation of a LAMP server (Linux, Apache, MySQL and PHP) is as simple as it gets, and for anyone who wants to get to PHP as fast as possible, I highly recommend this route.

It doesn't come without its drawbacks, though. Continuing our comparison, WordPress, as great as it is, loads a lot of functionality. If you're writing on a simple blog (like this one), that functionality may be overkill, and you may end up with a lesser performance profile than some of the more focused offerings. However, if you require a fair amount of the functionality and flexibility that WordPress provides, you will spend many hours writing a platform for that from scratch, with possibly negligible performance gains. Apache falls in the same boat, with the ability to use .htaccess files and load extra Apache modules at will (including PHP). However, for larger sites and due to the performance limitations of Apache at the time, the way was paved for a new web server.

NGINX

NGINX was built after Apache took its place as the server-du-jour for Linux. If you ran a linux server, you probably used Apache, and if you ran a Windows server, you probably used IIS. However, as the web evolved and millions of people began using the internet regularly, concurrency became a huge hurdle for Apache. At the core of Apache's functionality (now the MPM-Prefork module) was the need to spawn a process for every connection. That means every user currently browsing a given website needed a process, and processes are not cheap in terms of CPU. Large sites like social networking and news sites immediately began to feel the struggle -- this is where NGINX comes in.

In order to deal with concurrent connections in the tens of thousands, NGINX was built off of an event-loop. Basically, when many connections came in, one NGINX process would serve one connection after the other -- very quickly. Remember how Apache was a jack-of-all-trades? Each Apache process in this scenario had the capability to parse dynamic content like PHP and serve it. NGINX, on the other hand, simply passes it on to a "PHP Daemon", which is a mini server that is listening only for PHP requests. This means when NGINX responded to a request for an image, PHP was never loaded! The focus, then, for NGINX was to respond to as many requests as quickly as possible.

But what about now?

Apache has come a long way since then. It now offers different Multi-Processing Modules (MPMs) that change the way these handle requests. These MPMs are not like other Apache Modules -- they must be compiled into the server during installation. Once you've chosen an MPM, you'll have to recompile Apache in order to switch.

These modules are as follows:

  • MPM-Prefork
    The same as ever. One process spawns for each request. This is the only option for using mod_php built into Apache, and is the default

  • MPM-Worker
    Each process can spawn child threads, which reduces the overhead for concurrent connections. This isn't compatible with mod_php, but is mostly compatible otherwise. Each thread is left open for a connection, and will be used for loading assets and other files associated with a request.

  • MPM-Event
    Similar to MPM-Worker, except it will not leave threads waiting for connections. If using SSL or other modules, it will behave like MPM-Worker. This is only stable in Apache 2.4

As you can see, MPM-Worker and MPM-Event move towards the NGINX way of processing, where each process can process multiple concurrent connections. It is not the same, nor does it necessarily outperform NGINX, but it is useful when you want to use Apache and also handle concurrency.

These are not exclusive

I think the main reason that Apache continues to flourish is its ability to use .htaccess files to modify your configuration on a per-directory basis. It's sometimes easier to manage a site's .htaccess than it is to go through Apache or NGINX configuration files. WordPress, for example, will automatically generate your .htaccess file if it has write permissions on its own files. This means (both good and bad), that WordPress plugins can modify the rewrite rules in your .htaccess. Talk about customization! NGINX, on the other hand, is against ever doing this because they love an efficient server (and who doesn't?).

In order to get the best of both worlds, you can listen for traffic with NGINX, check if a static file exists at that location, and if it doesn't -- pass the request to Apache. Apache can then read its .htaccess files, and pass that information to PHP. If a static file exists, Apache and PHP processes are never spawned, and everybody wins.