Why You Should Consider Node.JS as a Backend Option for Your Project

January 28th, 2016

I. HISTORY OVERVIEW

In the early 2000s, when the web was small, servers were slow and client machines were even slower, developers faced the C10K problem. The problem was about concurrently handling 10,000 client connections on a single server machine. As a solution, multi-process and multi-threaded architectures (a new process or thread per each request) became very popular in mainstream software platforms for web development.

But the web continued to grow (and it still does), C10K goal became implementable on most software platforms and frameworks and the community stated the next goal - C10M problem. As you might have guessed, it’s about dealing with 10,000,000 concurrent client connections, which is a tremendous load.

The C10M problem is still relevant now and developers need new solutions to reach much higher load requirements. Most modern web apps include RESTful backend along with web and mobile apps that consume backend API. This increases load that the backend server should be able to hold.

Async I/O based platforms were created to help developers reach the goal. In this post we’ll talk specifically about Node.js as our preferred platform for high load systems development.

II. NODE.JS OVERVIEW

Node.js was initially created in 2009 by Ryan Dahl and other developers working at Joyent company (main contributor of Node.js). The idea was to use extremely fast Google V8 JavaScript engine and implement system libraries that provide common APIs which are absent in browser environments (as browsers provide sandboxes for JS code actually), like file manipulation, HTTP client/server libraries, and so on.

Because of async nature of JS (which is executed in a single thread and does not support multithreading at all), all of Node.js system libraries provide evented and asynchronous API for I/O operations, like reading a file or sending an HTTP request.

So Node.js itself might be described as an asynchronous event-driven platform. Code written by developers is executed in a single thread and, speaking of web backend development, at each moment of time only single client request is being processed, while all others are idle. However, due to the async nature of Node.js, all calls that are potentially blocking, like execution of SQL queries, have event-based API and lead to switching from current request processing to next awaiting operation (all of this is handled by the event loop).

test

III. COMPARISON WITH “CLASSICAL” SOLUTIONS

Let’s look at “classical,” thread-per-request based solutions, like Java servlet containers (Tomcat, Jetty, etc.) or Apache web server. By default, the whole thread is blocked on I/O operations here. Thus, maximum load that can be handled by a single web server instance is bounded by the maximum amount of threads that the server can handle.

Apart of the fact that creation of a new thread is relatively expensive, threads have quite a heavy footprint themselves. For example, each Java thread requires 1024KB of memory for its stack in 64-bit JVM, so 10K threads require 10Gb of RAM just for the thread stack.

So building highroad systems with such software platforms is still doable, but it’ll require many more server instances to handle the same load.

IV. OUR EXPERIENCE WITH NODE.JS

At DSR we have implemented several projects with Node.js-based backends and have been very pleased with the scalability and performance of the platform.

The strength of Node.js is the async, non-blocking I/O nature. Modern RESTful backends do a lot of I/O operations mostly, without involving heavy computations, and Node.js shines here. While reaching C10K goal requires certain effort from the developers on multi-threaded platforms, it’s just the worst performance level in case of Node.js.

Our experience confirms that Node.js is a stable and developer-friendly platform. Since Node.js 4.0, there are LTS releases now, which are stable and supported for a long period of time. As for developers, we find built-in platform tools, like npm, very handy, and, as for the code, promises cooked with generators are just simply awesome.

Of course, there are some negative points, like small amount of production-ready 3rd party libraries/frameworks. But the platform is rather young and Node.js ecosystem is rapidly growing and maturing. Growth of npm package count also indicates this well enough (see the chart below).

file

We’re actively participating in the Node.js platform community and are looking forward to building more great, high load systems using it.