According to Nodejs documentation, the most straightforward answer to the frequently asked question, "Is Nodejs single threaded?" is yes.
Nodejs applications run on a single thread by default. However, you can customize your application to use multiple threads using packages and modules like the worker_threads
module.
But how is Nodejs single threaded? This tutorial answers that question by explaining the concept of threads, and the synchronous vs asynchronous nature of Nodejs.
By the end of this tutorial, you will have decided how to effectively use the runtime environment. Let's get started.
Understand programs, processes, and threads
The first step toward discovering whether Nodejs is single threaded is understanding programs, processes, and threads.
The definition of a program may slightly differ when you think about a program from an imperative or a declarative programming perspective. Imperative programming entails giving line-by-line instructions, whereas declarative programming involves giving the structure of elements without writing the control flow.
Imperative programming defines a program as a sequence of instructions for a computer to execute in a programming language. On the other hand, declarative programming defines a program as a set of instructions.
A program under execution is called a process, and a thread is a basic unit of CPU utilization. A single program could have multiple processes. Similarly, each process could be associated with many threads.
A runtime environment that uses one thread per process is called single threaded. On the other hand, an execution environment that deploys multiple threads per process is called multi-threaded.
A single-threaded application performs one task at a time. Contrarily, a multi-threaded application performs many tasks at a time.
Since it can perform multiple tasks simultaneously, is Nodejs single threaded or multi-threaded?
It would be best to understand synchronous and asynchronous code before classifying the threading nature of Nodejs.
What is synchronous programming?
Failure to deeply understand the roots of Nodejs often leads to the question: Is Nodejs single threaded?
JavaScript was originally meant to achieve simple input-output tasks in the browser. For example, open a link, and get an alert message. Or click a button and change the background design.
You write a program.
const sum = 23 + 9
const name = 'Doe'
console.log(sum)
console.log(name)
The program is fed into the JavaScript engine in the browser. That happens through the browser APIs like the window and document objects.
The engine then reads your code from the top to the bottom of the page. A delay in the sum
computation would delay the printing of the name
.
The blocking, sequential reading of the code is called synchronous.
The weakness of the synchronous code is that an application is likely to become unresponsive. But how does JavaScript handle the problem? Find out below.
How JavaScript code runs asynchronously
JavaScript uses events to avoid blocking the user interface. Different events get attached to various callback functions. The result is an event loop, also called the event queue.
So, a function runs only when an event is triggered, and the execution of one function does not block the triggering of another event.
JavaScript engines like SpiderMonkey (Mozilla) and V8 (Chrome) use one thread to serve multiple programs.
The thread monitors the event loop for requests and fetches the responses.
While a response is getting fetched, the thread revisits the event loop to receive another request. The thread gets a notification when a response arrives. It then submits the response and returns to receive orders or deliver responses. Consequently, requests don't wait for preceding orders to be completed before they can be handled.
The ability of JavaScript to complete multiple tasks deploying a single thread to monitor events is called event-driven, non-blocking I/O. When Nodejs, the runtime environment for JavaScript, was invented, it utilized the event-driven I/O.
Is Nodejs single threaded? Nodejs versus the browser API
The combination of a C++ program and the V8 engine resulted in Nodejs. Nodejs makes it possible to interact with the operating system without using the browser. You can then write programs that do more complex activities like directly communicating with the file system or building a server.
This time around, we don't use the window
and document
objects. Instead, Nodejs uses the global
API, which applies the process
object extensively. However, specific APIs like the setTimeout
and fetch
(available in Nodejs versions above 17.5) exist in both browser and Nodejs.
Nodejs uses the non-blocking event-driven architecture. That answers the typical question: Is Nodejs single threaded? But how is Nodejs single threaded and still manages to do complex tasks that JavaScript was originally not meant to do?
How Is Nodejs single threaded?
Earlier I told you that JavaScript code is synchronous but can run asynchronously using events. Events, in turn, deploy callbacks, which are monitored by a single thread through the event loop.
Nodejs has a similar design. The only difference is that most modules are asynchronous by default. Here are two examples illustrating the concept of single-threaded, non-blocking I/O.
Example-1: Writing a file
The fs
module, that handles the filesystem activities, has default asynchronous methods like readFile()
.
const fs = require('fs')
fs.writeFile("file.js", "console.log('is Nodejs single threaded?')", (error) => {
if (error) throw error
else console.log('File written successfully!')
})
The first part of the method is the file name, the second part is the data to write in the new file, and the last part is a callback function. The callback function waits for the file writing process to complete before giving a response. It will throw an error or print a success message on the console output.
So, while the callback function waits for the request, the single thread is busy serving other parts of the code without blocking the I/O. As soon as the response is back, the single thread delivers it.
Example-2: Creating a server
The http
module, too, deploys the concept of a single thread, event-driven I/O.
const http = require('http')
const callbackFunction = (request, response) => {
if (request.url === '/') response.end('Request received')
else response.end('Wrong route!')
}
const server = http.createServer(callbackFunction)
server.listen(5000)
The single thread pushes the callbackFunction
to the event loop when the server receives the request event. In the event loop, the callbackFunction
is executed. While that is happening, the single thread monitors another activity, for example, writing or reading files.
When the process is completed, the server sends a response to the client. And if there is no more request from the client, the callback function is popped off the callback queue.
Another way to create and handle asynchronous code is to use promises, mainly built-in external APIs. They are added to the promise queue and managed similarly to callback functions.
As a result, it is advisable to use Nodejs for I/O operations and not CPU-intensive operations. However, if you must run CPU-intensive tasks, use the setImmediate, cluster, or the worker_threads modules as explained in this article.
Conclusion
Finding the answer to the question, "Is Nodejs single threaded?" entails understanding threading, asynchronous programming, and the event loop.
As explained in this tutorial, you can then use Nodejs for non CPU-intensive tasks. Otherwise, you can apply the recommended ways to achieve multithreading.