The Node.js Architecture!
By: Aditya Channe
Tags: Nodejs, Backend, Development, JavaScript, Developer

Hello, everyone. I hope you are doing good! Today, in this article, I’m going to discuss the working of awesome node.js. A deep dive into what happens as the code runs in the node runtime. Its core libraries, dependencies, and the brain of node.js.

Node.js is written not only in Javascript alone but in c++ and Javascript to operate correctly. There are many libraries upon which node depends. However, V8 and LIBUV are the two foremost dependencies that handle the majority of node.js operations.

These two dependencies provide a very nice abstract layer and allow us to write pure JavaScript code that runs in Node.js and still giving us access to file-reading features that are actually implemented in LIBUV and other C++ libraries behind-the-scenes. The beauty of all this is that Node.js binds all these libraries together, irrespective of whether they are written in C++ or JavaScript, and then gives us access to their functions in pure JavaScript. It makes it much easier for us to focus on the application code, without having to deal with the C++ code.

Let’s explore them one at a time now.

V8

Node.js is built on the V8 engine of Google. It is the fastest javascript engine. The V8 engine converts the javascript code into the machine code which the computer actually understands. The result is then generated and returned to node.js. Node.js cannot understand the javascript code we write without V8. Besides javascript, V8 also uses C++.

**Before Starting with LIBUV you should have a basic understanding of Asynchronous I/O.

Asynchronous Input-Output

The Asynchronous I/O allows applications to overlap processing with I/O operations. In simple words, the goal is that the program should never block.

In synchronous I/O the Thread (a thread is just a sequence of instructions) will wait till the entire operation is finished. On the other hand in Asynchronous I/O, the thread does not wait during the operations. The operation will run in the background and it will be called when it is finished. The Asynchronous I/O feature enables an application to have more CPU time available to perform other processing while the I/O is taking place.

LIBUV

LIBUV is another major dependency on node.js. It gives node.js access to the machine operating system, networking, file system, and more. LIBUV is an open-source library with a strong focus on asynchronous I/O (Input-output). LIBUV is written in C++. Apart from focusing on the asynchronous I/O LIBUV also implements two important features which are event loop and thread pool.

Event Loop is responsible for handling simpler tasks and the thread pool manages the heavy tasks. Let's explore them one by one.

Event Loop

When we use Node.js on a computer, it means that there is a node process running on that computer. The process is just a program in execution. Now in that process, Node.js runs in a single thread. A thread is basically just a sequence of instructions and It’s not essential to deeply understand what a thread or a process is. Just imagine a thread as being a box where our code is executed in a computer’s processor. Now, what is essential to understand here, is the fact that node runs in just one thread, for example, if we have 4 different tasks then all these four tasks will happen in one single thread.

In languages like PHP, we have one new thread created for every task. So, again, if you run your Node application, it will run in just a single thread. No matter if you have 1 user or 100 users or maybe 100 million users accessing your application at the same time. The event loop is called the heart of the node.js. It executes all the callback functions( functions that are called as soon as some work is finished) in a single thread and it also offloads heavy or expensive tasks like compressing a file to a thread pool. Eventloop makes asynchronous programming possible in node.js. I will talk about asynchronous programming in my next article.

It takes care of all the incoming events and performs the balancing part by offloading heavier tasks into the thread pool, and doing the simpler tasks by itself. I will talk about the Event loop again in the next few articles because there's a lot more to it and it is the most important feature in node.js. For now, you should remember one thing that the Event Loop is the heart of Node js, which makes the node completely different from other backend languages.

Thread Pool

The thread pool gives us four additional threads that are completely separate from the main single thread in the event loop. We can configure it up to 128 threads, but usually, these four are enough. So these four threads together formes a thread pool. The event loop will offload the heavy tasks to the thread pool and this happens automatically behind the scenes. It’s not us developers who decide what goes to the thread pool and what doesn’t. Some of the expensive tasks that get offloaded are all operations dealing with files, everything related to cryptography, like caching passwords, then all compression related operations, the DNS lookups(matches web domains to their corresponding real IP addresses), and more. This is something that would most easily block the main thread. So, Node takes care of it by automatically offloading them into the thread pool.

For example- Here when the request hits the node server it will go to the event loop through the event queue. Now the event loop will check whether the task is a heavy task like operations dealing with files or network-related operations. If the task is heavy it will offload it to the thread pool where the thread pool will execute the task separately. it will not block our event loop and the event loop can perform all the less complex tasks

Other Important Libraries

The most critical libraries for Node.js are LIBUV and V8. However, the node is not only based on V8 and LIBUV, but also on few other libraries like HTTP parser for parsing HTTP, C-ARES for DNS queries, OpenSSL for cryptography, and Zlib for file compression. when all of these components come together perfectly, we end up with Node.JS ready to be used on the server-side for all of our applications.

Event-Driven Architecture

Most of the Node’s core modules, like HTTP, File System are built around an event-driven architecture. The concept is actually quite simple. In Node, there are certain objects called event emitters that emit named events as soon as something important happens in the app, like a request hitting server or a file finishing to read. These events are then picked up by event listeners that we developers set up, which will fire off functions(callback functions) that are attached to each listener.

on one hand, we have event emitters that will emit named events, and on the other hand, we have event listeners that react to emitted events by calling the callback functions. The event-driven architecture makes it way more straight forward to react multiple times to the same event. All we have to do is to set up multiple listeners.

Okay, so this is the Node’s event-driven architecture in a nutshell. Don’t worry if this seems a bit too theoretical, I will explain more about the events and callback functions in the next article and we will also see this logic being used in many situations. so see you in my next article. Have a great day!

Gain Access to Expert View — Subscribe to DDI Intel