What kind of web server should I use for my app?


So you’re trying to build a web app, huh? You’re going to need to serve it from somewhere. So do you go with Apache? Perhaps something lighter like Lighttpd or Nginx? What about picking a server-side language? Java? PHP? Or perhaps you just go with a JavaScript solution and pick Node? Let’s examine the differences in these choices.

Quick overview

When it comes to synchronous servers, Apache is undoubtedly the most popular. In a synchronous server, each simultaneous connection requires a thread, which in turn, requires some overhead. On the other hand, an asynchronous server is event-driven, and mostly handles all requests in a single thread. Asynchronous web servers include the more lightweight Lighttpd and Nginx, as well as Node’s HTTP server. They use a non-blocking I/O event loop running in a single process to serve requests.

If all you need is a simple HTTP server to serve some static files, then perhaps you should go with Lighttpd. It has an easy setup and is a nice alternative to Apache because it is performant and simple. Furthermore, most of the good parts of Apache are also available in Lighttpd including modules, URL rewriting, and support for CGI or FastCGI. To get going, just install the lighttpd package in your Linux distribution, run the server start command, and watch pages get served! If you do use FastCGI, it will actually allow you to use separate processes for each request, processed on a separate server, which is good for isolating processes from your main server for reasons of security or stability.

Nginx, another asynchronous open-source, lightweight  HTTP server, has many similarities to Lighttpd; It also uses one master process to serve requests; however, it actually delegates its work onto separate worker processes, which is great for taking advantage of a machine’s multiple cores. Just like Lighttpd, it’s fast and efficient at serving static content, but it seems to be more performant than Lighttpd. Nginx keeps a small memory footprint, even with lots of traffic, and is known to be pretty stable.

So let's take a look at Apache and Node in more detail.


Why is Apache the most popular web server? For starters its .htaccess file allows for flexible configuration, it’s the standard server bundled in typical LAMP setups, and it’s easy to find solutions to any problems with it. It generally uses PHP, which is easy for beginners and works well for serving web pages. It’s been around for a while, which means it’s quite stable. Since it is thread-based, an unexpected problem occurring while processing a request, will only crash one thread, and therefore isolate the issue to one request. In general, requests do not block each other in any way on the server. Apache has a lot of modules available for it so it is very configurable to fit your needs. Having said that, the knock on Apache is that it is “heavy” compared to servers like Lightpd and Nginx. It is quite resource-hungry by default, and can quickly gobble up RAM because it uses a different thread (and sometimes process) for each request.


So now we get to Node, a JavaScript platform that has a server-side JavaScript runtime environment (V8) and comes with a standard HTTP server. Overall, node is asynchronous and uses a non-blocking I/O event loop. Every request runs in the same thread, which means it can handle concurrent requests much better than Apache. It is a perfect candidate for realtime communication over the web, is lightweight like Lighttpd or Nginx, and scales well due to its asynchronous nature.

So can you perhaps call it a JavaScript version of Lighttpd or Nginx? Well, one major difference is that it has the tools to both build an application and serve it; in fact, both the server and the application are configured and written by the developer using the same language. Since JavaScript is the language of the web developer nowadays, it makes it easy to learn Node and even create isomorphic solutions with it (code shared between client and server). Benchmark tests also show that Node greatly outperforms PHP/Apache setups in serving concurrent requests and in response times as server loads increase, although running PHP with HHVM has come closer to narrowing this gap.

Of course, there are some drawbacks with Node. Since all requests run on the same process, you better hope that you designed your application correctly, or there will be consequences. One bad request could hog up the resources needed to process other requests and even crash your whole application. This is why in node, it’s usually a good idea to use exception-based logic as well as delegate CPU-intensive requests to a worker or some other process. Another knock on Node is that it is still relatively new compared to other server/application architectures. Also, serving static files is slower in Node than it is in Apache.

But there is a way to handle multithreading in Node applications. Namely, Node handles multithreading for you via the libuv library. You already avoid access collisions within the shared memory space because JavaScript is single-threaded, but with libuv in the mix, you gain speed benefits as well. Asynchronous non-blocking I/O APIs allow you to utilize background threads to do work behind the scenes while the main event loop continues to check the background processes roughly every 20 milliseconds. JXCore, a Node.js fork, is not open-source but has some nice features for Node multithreading including the ability manage child processes efficiently. The child forks are nicely separated from the main thread while allowing them to still share resources in a multithreaded way.


As far as languages go, you would typically use something like Java or PHP on a synchronous server like Apache. These languages can handle working with separate threads nicely and are generally used for synchronous processing; however, they also come with asynchronous capabilities when needed. JavaScript, the language of the Node.js environment, on the other hand, is by nature meant to be run in an asynchronous environment such as the V8 engine inside of Node.

…so there you have it. Hopefully you choose the right web server and application architecture that suits your needs!

Jeff Poyzner