Node.js is ideal for building highly scalable, data intensive, real-time back-end services that power our client applications. You might ask but there are other tools and frameworks out there for building back-end services such ASP.NET, Rails, Django, etc., why choose Node? Before answering the question, let’s understand Node.js architecture.
Node’s “Single Thread” Architecture
Node applications are highly scalable because of the non-blocking or asynchronous nature of Node. What do you mean by asynchronous? As a Node.js developer, let me give you an analogy.
You go to a restaurant. A waiter comes to your table, takes your order, and gives it to the kitchen. Then the waiter moves to serve another table while the chef is preparing your meal. The same waiter can serve many different tables and don’t have to wait for the chef to cook one meal before serving another table.
This is what we call non-blocking or asynchronous architecture and this is how Node applications work. The waiter is like a thread allocated to handle a request. So a single thread is used to handle multiple requests.
In contrast to non-blocking or asynchronous architecture, we have blocking or synchronous architecture. To understand the latter architecture, let’s go back to our restaurant analogy. You go to another restaurant, and in this restaurant, a waiter is allocated to you. The waiter takes your order and gives it to the kitchen. Now he is sitting in the kitchen waiting for the chef to prepare your meal, not doing anything.
One way to look at this analogy is this that the waiter is just waiting. He will not take an order from another table until your meal is ready. This is what we call blocking or synchronous architecture. Now, coming back to your question, that’s how applications built with frameworks like ASP.NET, Rails, and Django work out of the box.
In this architecture, when a server receives a request from the client, the thread is allocated to handle that request. As a part of handling that requests, the thread might query a database, which may take a little while until the result is ready. When the database is executing the query, that thread is sitting there waiting. It can’t be used to serve another client’s request and the server has to allocate it another thread.
If we have a large number of concurrent clients with their requests, at some point we’re going to runout of threads to serve these clients. New clients have to wait until free threads are available. If we don’t want them to wait, we need to add more hardware. That’s why Node.js development companies are in great demand these days.
A real-life example
The real-time chat app to support your helpdesk is based on blocking or synchronous architecture and, consequently, for each new conversation, the app creates a new thread. Let’s say each thread occupies 2MB of RAM and the server has 8GB of RAM installed. The RAM will max out at 4000 concurrent conversations. If you have managed a chat support center, then you know 4000 conversations at a time aren’t surprising. Upgrading server, we all know is a costly affair.
In contrast, a Node.js based real-time chat app can, virtually, achieve scalability levels of over 1M concurrent conversation on a single thread in the same amount of RAM. Of course, even the largest of support centers don’t process this many requests at a time. This is the magnitude of scalability a Node.js application can deliver.
Node’s “Single Thread” Advantage
In blocking or synchronous architecture, we are not utilizing our resources efficiently. That’s why applications built with frameworks like ASP.NET aren’t exactly scalable as they max out at the hardware’s maximum ram.
Node web server accepts requests and puts them in event queue. The web server continuously polls for new requests from client in an infinite loop called Event Loop. Event loop is at the heart of Node.js applications and gives them the unparalleled scalability I am talking about.
The event loop operates under single thread in Node. The event loop runs endlessly across the event queue, seeking new client requests. If it finds a new request in the queue, it will flag it as either blocking or non-blocking. The event loop will process the non-blocking request and send the response to user.
Things get a little interesting when the request requires server to perform a blocking I/O operation like accessing the file system or raising a SQL query. In that case, event loop assigns that request a thread and goes about polling for fresh requests in the event queue. The thread, in the meanwhile, processes the thread, performs blocking operations, and sends it back to the event loop with a response. The event loop sends the response back to the client.
An ideal architecture to build scalable apps
Asynchronous architecture makes Node ideal for building applications that include a lot of disk or network access. Your application can serve more clients without the need to throw in more hardware. Thus, Node.js applications are highly scalable.