# How Node.js Handles Multiple Requests with a Single Thread

## Introduction

If you come from languages like Java or C++, Node.js feels confusing at first.

One thread. Thousands of users. APIs responding instantly. Chats updating in real time.

Most beginners hear:

> “Node.js is single-threaded.”

…and assume it can only handle one user at a time.

That is not true.

Node.js works differently from traditional backend systems. Instead of creating many threads for every request, it focuses on efficient task handling using:

*   Non-blocking I/O
    
*   Event Loop
    
*   Background workers
    
*   Asynchronous execution
    

The result is a backend runtime capable of handling massive numbers of concurrent requests efficiently.

* * *

# Single-Threaded Nature of Node.js

Node.js mainly runs JavaScript on a **single main thread**.

That means:

*   One thread executes JavaScript code
    
*   Tasks are processed sequentially
    
*   Only one piece of JavaScript runs at a time
    

This sounds limiting at first.

But the important detail is:

> Node.js avoids waiting.

Traditional servers often waste time waiting for:

*   Database responses
    
*   File reads
    
*   API calls
    
*   Network operations
    

Node.js delegates these operations instead of blocking the main thread.

* * *

# Thread vs Process

Before understanding Node.js properly, it is important to understand the difference between a process and a thread.

## Process

A process is an independent running application.

Examples:

*   Chrome
    
*   VS Code
    
*   Spotify
    

Each process has its own memory space.

* * *

## Thread

A thread is a worker inside a process.

Think of it like this:

*   Process = Restaurant
    
*   Threads = Workers inside the restaurant
    

Traditional backend systems create many threads.

Node.js mainly uses one main thread for JavaScript execution.

* * *

# Chef Handling Orders Analogy

Imagine a restaurant.

## Traditional Blocking Server

A chef takes one order.

Customer says:

> “Make biryani.”

The chef:

*   Starts cooking
    
*   Waits for rice
    
*   Waits for ingredients
    
*   Waits for everything
    

Meanwhile, every other customer waits.

This approach does not scale efficiently.

* * *

## Node.js Style

The chef takes an order.

Rice needs 20 minutes?

The chef says:

> “Kitchen handle this. Next order.”

Then the chef immediately handles other customers.

When the rice is ready, the kitchen informs the chef.

The chef then finishes serving.

In Node.js:

*   Chef = Event Loop
    
*   Kitchen workers = Background workers / OS APIs
    

This is why Node.js performs extremely well for APIs and real-time applications.

* * *

# How Node.js Handles Multiple Requests

Suppose multiple users hit the server at the same time.

```js
app.get("/", async (req, res) => {
  const data = await fetchData();
  res.send(data);
});
```

Here is what happens internally.

* * *

## Step 1: Request Arrives

Node.js receives the request.

The main thread processes it quickly.

* * *

## Step 2: Slow Operation Detected

`fetchData()` may:

*   Read from database
    
*   Read a file
    
*   Call another API
    

These are slow I/O operations.

Instead of waiting, Node.js delegates them.

* * *

## Step 3: Background Workers Handle the Task

The task is delegated to:

*   Operating System
    
*   libuv thread pool
    
*   External systems
    

Meanwhile, the main thread becomes free immediately.

It can now handle other incoming requests.

* * *

## Step 4: Event Loop Checks Completion

Once the task finishes, the event loop notices it.

The callback or promise is pushed into the queue.

Then Node.js executes the callback and sends the response.

* * *

# Event Loop and Concurrency

The event loop is the core mechanism behind Node.js concurrency.

Its job is to:

*   Monitor completed async tasks
    
*   Handle callbacks
    
*   Execute queued operations
    
*   Keep the server responsive
    

Simplified version:

```js
while(true){
   checkCompletedTasks();
   executeCallbacks();
}
```

This is not the actual implementation, but it helps understand the concept.

* * *

# Concurrency vs Parallelism

Many beginners confuse these terms.

## Concurrency

Handling many tasks efficiently.

Example:

One chef managing multiple orders.

Node.js mainly uses concurrency.

* * *

## Parallelism

Actually performing multiple computations simultaneously.

Example:

Multiple chefs cooking at the same time.

CPU-heavy systems rely on parallelism.

* * *

# Node.js Emphasizes Concurrency

Node.js is excellent for:

*   APIs
    
*   Real-time chats
    
*   Streaming platforms
    
*   Dashboards
    
*   Live collaboration apps
    

Because most of these applications spend time waiting for I/O operations.

Node.js avoids blocking during this waiting period.

* * *

# Why Node.js Scales Well

Traditional threaded servers:

*   Need memory for every thread
    
*   Require context switching
    
*   Increase CPU overhead
    

Node.js reduces these costs because:

*   Fewer threads are used
    
*   Non-blocking architecture improves efficiency
    
*   The event loop keeps the system responsive
    

This allows Node.js servers to handle very large numbers of concurrent connections.

Companies like Netflix and LinkedIn adopted Node.js for parts of their backend systems because of this scalability.

* * *

# Important Limitation

Node.js is not ideal for CPU-heavy operations.

Example:

```js
while(true){}
```

This blocks the single thread completely.

As a result:

*   No other requests can be handled
    
*   The server freezes
    

CPU-intensive tasks should use:

*   Worker Threads
    
*   Clustering
    
*   External services
    

* * *

# Diagram Idea 1: Single Thread Handling Multiple Requests

```text
Client Requests
      ↓
 Main Thread
(Event Loop)
      ↓
Delegates Slow Tasks
      ↓
 Background Workers
      ↓
Task Completion
      ↓
 Callback Queue
      ↓
 Responses Sent
```

* * *

# Diagram Idea 2: Event Loop + Worker Thread Interaction

```text
Request A ─┐
Request B ─┼──> Event Loop
Request C ─┘         │
                     ▼
           Background Workers
                     │
                     ▼
              Completed Tasks
                     │
                     ▼
                 Responses
```

* * *

# Simple Async Example

```js
const fs = require("fs");

console.log("Start");

fs.readFile("data.txt", "utf8", (err, data) => {
  console.log(data);
});

console.log("End");
```

### Output

```text
Start
End
[file content]
```

The file operation runs asynchronously.

Node.js does not wait for the file to finish reading.

* * *

# Final Thoughts

Node.js handles multiple requests efficiently not by creating countless threads, but by minimizing waiting.

Its event loop delegates slow tasks, handles callbacks, and keeps the server responsive.

The real strength of Node.js is:

> Efficient concurrency, not raw parallel execution.

That architectural decision made Node.js one of the most popular backend technologies for modern web applications.

* * *

# Specifications (Deep Dive)

## Core Components

| Component | Role |
| --- | --- |
| V8 Engine | Executes JavaScript |
| Event Loop | Manages async execution |
| libuv | Handles async I/O and thread pool |
| Callback Queue | Stores completed task callbacks |
| Worker Threads | Handle CPU-heavy tasks |

* * *

## Tasks Delegated to Background Systems

### OS Handled

*   Network requests
    
*   Socket operations
    

### libuv Thread Pool

*   File system operations
    
*   DNS lookup
    
*   Some cryptography operations
    

Default thread pool size:

```bash
4
```

Can be increased using:

```bash
UV_THREADPOOL_SIZE=8
```

* * *

## Event Loop Phases

Node.js event loop phases:

1.  Timers
    
2.  Pending callbacks
    
3.  Idle/prepare
    
4.  Poll
    
5.  Check
    
6.  Close callbacks
    

Understanding these phases becomes important when working deeply with:

*   Promises
    
*   Timers
    
*   Microtasks
    
*   Async behavior
    

* * *
