Apache and Nginx are two of the most popular web servers powering the internet today. According to BuiltWith, both of these constitute 50-55% of the total Web Servers on the internet. While both offer similar features, you shouldn’t randomly choose one over the other.
Since these two are very similar, many people who are exploring the web servers world find it difficult to choose which one to use for their project. In this article, we are going to discuss the major difference between the two and answer some key questions such as: Which one gives the best performance?. Which one is easy to set up? And so on. Each server has its own merits and demerits and you should carefully consider which one is best suited for your project.
We will compare the two based on 4 main features that everyone looks for when choosing a web server: Performance, Security, Ease of Installation, and Flexibility. These three features should be good enough for anyone to figure out which web server is best in which scenario.
Before we take a deeper dive into the comparison of Apache and Nginx, let us look at some history and background of the two. We will look into Apache first since it came before Nginx.
Apache played a very key role in the initial growth of the world wide web. The Apache webserver was released in 1995 by Robert McCool. After it’s the first release, Apache rapidly conquered the server market and became the world’s most popular web server. Because of this popularity, Apache quickly developed a pretty big community of users which provided great support and documentation for the project. Other software projects such as databases and server operating systems started to provide integration support for Apache. Soon after that, Apache came pre-installed with all major Linux distributions, like Red Hat/Centos and Ubuntu. It also integrated pretty well with PHP which was the most popular programming language for the web at that time.
Today Apache is mainly managed by the Apache Software Foundation. The server is developed and maintained by an open community of developers. According to the statistics, it runs 46% of the total websites on the internet.
Now that we have a brief overview of Apache, let us dig deep into the architecture of the server. Apache uses a process-driven approach to handle incoming requests. In other words, Apache creates a new thread every time to handle an Incoming connection request. This clearly works and provides good performance when you have a server with multiple cores. But for smaller services there aren’t many cores or resources for Apache to create new threads Hence, its performance tends to slow down as the number of cores decreases.
Another great benefit of Apache is its flexible request handling architecture. It gives the system admins the option to choose what type of request handling architecture they want to use on their server. Apache comes with three request handling modules commonly referred to as multiprocessing modules. They are mpm_prefork, mpm_worker, and mpm_event modules.
By default, Apache is configured with this module. This module creates new processes with a single thread to handle incoming requests. Each thread can handle a single connection at a time. This module functions smoothly as long as the number of requests is less or equal to the number of processes. However, it quickly becomes inefficient when the number of incoming requests surpasses the number of available processes. Whenever a new process is spawned, a significant chunk of memory is assigned to this process. As you keep spawning more and more processes, the amount of memory available decreases and performance starts degrading. The mpm_prefork module is usually not recommended because it cannot be scaled effectively.
This module is quite similar to the mpm_prefork module. The only difference is, instead of spawning processes with a single thread, it spawns processes that can handle multiple threads. Threads are very lightweight and consume much less memory compared to a process. At any given point in time, the number of threads will be always more than the number of processes. This means we don’t have to necessarily create a new process for each request. We can use the already existing threads to handle the request.
This module is preferred on high traffic websites because it has the ability to handle a large number of requests while using a very low amount of memory. By design, it is similar to the mpm_worker module but is highly optimized to handle keep-alive connections. In the MPM worker module, the threads are not released until and unless the connection is close. In the MPM event module, a dedicated thread is assigned to handle the Keep alive connections. This thread is only responsible for handling the connections and not processing the request. The processing part is forwarded to a worker pool or a thread pool.
Nginx was designed specifically to address the performance limitations faced by Apache. Nginx was first released as an open-source project in 2004. It was developed by a Russian developer named Igor Sysoev. Initially, Igor developed Nginx as a scaling solution for a popular Russian website Rumbler.ru where he worked as a system administrator. At Rumbler he was challenged to find a solution to the C10K problem. At that time the internet was growing massively and many big websites were receiving millions of visitors per month. All big websites faced one common issue, their web servers couldn’t handle more than 10k concurrent connections. Igor was very keen on solving this problem. He has realized that the existing servers at that time couldn’t solve this problem with minor tweaks and patches. So, he designed Nginx completely from the ground up with a new request handling architecture that was much more efficient compared to the architecture of the other web servers at that time.
After it was released, Nginx was used mostly to serve static files and as a load-balancer or reverse proxy in front of Apache. Since then it grew in popularity mainly because of its low resource consumption and its ability to scale easily on minimal hardware. Today Nginx comes in 2 versions. One is the open-source version, which everyone is familiar with and the other one is the Nginx Plus version which comes with support and additional enterprise features. Traditional web servers or application servers use the standard threaded or process-based architecture. Nginx uses asynchronous, non-blocking, event-driven architecture for request handling which enables it to scale to hundreds of thousands of concurrent connections. This sophisticated architecture consumes low memory and offers a very high level of concurrency.
Nginx creates 4 types of processes. The master process, the worker process, the cache loader process and the change management process. The master process is responsible for spawning all the remaining processes mentioned above. It also takes care of binding ports and reading configurations. The cache loader is responsible for loading the cache from the disk to the memory. The cache manager process runs periodically and makes sure that redundant cache is removed from the disk storage. The worker processes are responsible to do all the heavy lifting. They handle connections, read and write to disk, and communicate with other servers. The number of worker processes it creates is usually limited to the number of cores available on the machine. In March 2019, Techcrunch reported that Nginx was powering more than 375 million websites.
Let us first compare both the static and dynamic caching abilities of the two web servers. Nginx is much faster compared to Apache when it comes to static caching. It was designed to serve static content with low memory consumption hence it is the best option for static caching. Nginx is not suited for dynamic processing. Unlike Apache, Nginx forwards the dynamic processing part to a separate external server via the FastCGI protocol and waits for the response. Apache on the other hand can process dynamic content by embedding the processor of languages such as PHP in its worker processes. Nginx comes with the FastCGI caching module inbuilt for dynamic caching and Apache comes with the mod_cache. Both modules have similar performance when it comes to dynamic caching.
Both Apache and Nginx use different architectures underneath to handle requests. As mentioned earlier the architecture of Apache is much more modular. You can swap a couple of modules in Apache and you get a different request handling architecture. This is not the case with Nginx. Nginx uses asynchronous, non-blocking event-driven architecture. Nginx is optimized for low usage of memory and a high level of concurrency. This makes it possible for Nginx to handle thousands of requests concurrently. Apache on the other hand uses threaded or process-based architecture to handle requests. This type of architecture does scale well when hit with high volumes of connections. The mpm_event module improves the performance quite a bit but still, it’s not as good as Nginx.
Operating System Support
Apache supports all Unix-based operating systems such as Linux and macOS. It also has good support for Windows. Nginx is also well supported on Unix based operating systems but has very limited support in Windows. Apache clearly wins her.
You can customize Apache by writing your own modules and loading them dynamically. Dynamic loading was one of the major reasons why Apache was widely accepted. All of its modules have great support for dynamic loading. Currently, Nginx has very limited support in dynamic loading but it is expected to improve over time.
We hope this article gave you a good understanding of the key differences between the two servers. Nginx is the best option to use when you have a website that gets heavy traffic. You can use it standalone or in combination with Apache. Both servers are powerful and capable. At the end of the day choosing which server to use in your project largely depends on your requirements and needs.