# How Node.js Actually Works

When people start learning **Node.js**, they often hear statements like:

*   *Node.js is single-threaded*
    
*   *Node.js is non-blocking*
    
*   *Node.js uses an Event Loop*
    

But what actually happens **inside Node.js** when we run a program?

What happens when we execute:

```javascript
node index.js
```

How does Node.js handle:

*   File reading
    
*   API calls
    
*   Timers
    
*   Database queries
    

while still remaining **fast and scalable**?

To understand this, we must understand **three core components** of Node.js:

1.  **V8 Engine** – executes JavaScript
    
2.  **libuv** – handles asynchronous operations
    
3.  **Event Loop** – coordinates everything
    

Let’s explore them step by step.

* * *

## 1\. What Exactly is Node.js?

Before diving deeper, we must clear one important confusion.

**Node.js is NOT a programming language.**

Node.js is a **JavaScript runtime environment**.

This means Node.js provides everything required to **run JavaScript outside the browser**.

A Node.js runtime contains multiple components:

*   JavaScript Engine (V8)
    
*   Event Loop
    
*   libuv threadpool
    
*   OS bindings
    
*   memory management
    
*   networking APIs
    

**In simple terms:**

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/a8a1f73d-8327-4493-87c8-d45dfae08cdb.png align="center")

* * *

## 2\. Understanding Runtime with a Simple Analogy

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/6d9cc033-b10f-4e2c-83a0-1ce93fb22029.png align="center")

Similarly:

```javascript
Your Code → JavaScript

Player → Node.js Runtime
```

Node.js provides the **environment required to run JavaScript**.

* * *

## **3\. What is a JavaScript Engine?**

A JavaScript engine is a program that executes JavaScript code. Most engines today are built with similar core components:

*   **Parser**: Transforms source code into an Abstract Syntax Tree (AST)
    
*   **Interpreter**: Executes the code line-by-line initially
    
*   **JIT Compiler**: Compiles hot code paths into optimized machine code
    
*   **Garbage Collector**: Reclaims memory no longer in use
    

###   
❊ **Key JavaScript Engines**

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/bc3aed28-b04d-49b6-a6e6-6d98e3fc8d09.webp align="center")

* * *

### 4\. The V8 Engine – The Heart of Node.js

*V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.*

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/b260ae38-d7bb-4b7c-be6a-628c1106b26b.png align="center")

At the core of Node.js lies the **V8 JavaScript Engine**.

V8 was developed by **Google** and is also used in **Chrome**.

Its job is simple:

> Convert JavaScript code into machine code so the computer can execute it.

## ❊ What V8 Actually Does

V8 performs several critical tasks:

*   Parses JavaScript
    
*   Compiles JavaScript into machine code
    
*   Executes code
    
*   Manages memory
    
*   Runs garbage collection
    
*   Maintains the call stack
    

### **Workflow**

1.  **Parsing**: JavaScript is parsed into an AST.
    
2.  **Ignition (Interpreter)**: Executes unoptimized bytecode quickly.
    
3.  **Turbofan (JIT Compiler)**: Optimizes frequently executed code into fast machine code.
    

### **Example**

```javascript
function square(n) {
  return n * n;
}

console.log(square(5)); // 25
```

*   Initially run by Ignition
    
*   Optimized by Turbofan if called repeatedly
    

* * *

### 5\. Call Stack – Where Code Executes

Inside the V8 engine there is a **Call Stack**.

The call stack keeps track of **which function is currently executing**.

Example:

```javascript
function greet() {
  sayHello();
}

function sayHello() {
  console.log("Hello");
}

greet();
```

Execution order:

```plaintext
Call Stack

 console.log 
 sayHello()  
 greet()     
 global()    
```

Functions enter the stack when called and leave after execution.

This is why JavaScript is called **single-threaded execution**.

Only **one function executes at a time** in the call stack.

* * *

### 6\. The Problem with Synchronous Code

Imagine Node.js handled everything synchronously.

Example:

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

const data = fs.readFileSync("bigFile.txt");
console.log(data);
```

If the file takes **5 seconds** to read, the entire program stops.

Nothing else runs.

This is called **blocking behavior**.

Node.js solves this problem using **asynchronous architecture**.

And that is where **libuv** comes in.

* * *

### 7\. libuv – The Hidden Power of Node.js

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/d16608af-aa36-4f50-96f0-ad63696f9bf5.png align="center")

**libuv** is a C library used internally by Node.js.

Its job is to handle **asynchronous operations**.

Examples:

*   File system operations
    
*   DNS lookups
    
*   compression
    
*   cryptography
    
*   background tasks
    

### ❊ libuv Threadpool

libuv provides a **threadpool**.

By default:

```plaintext
Threadpool Size = 4 threads
```

These threads run **heavy operations in the background**.

Example:

```plaintext
Read File
Hash Password
Compress Data
Write File
```

These tasks are executed **without blocking the main thread**.

You can even change the threadpool size:

```javascript
process.env.UV_THREADPOOL_SIZE = 8;
```

* * *

### 8\. Event Loop – The Coordinator

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/ac3693b4-ecd8-47f1-a471-412ec067417a.png align="center")

The **Event Loop** is the central coordinator of Node.js.

It constantly checks:

```plaintext
Is the call stack empty?
```

If the stack is empty, it pulls tasks from queues and executes them.

### ❊ Simple Event Loop Flow

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/84808fe0-fa2f-4071-bd93-152c29a0cd7c.png align="center")

This loop runs **continuously** while the Node.js process is alive.

### ❊ Example to Understand Event Loop

```javascript
console.log("Start");

setTimeout(() => {
  console.log("Timer finished");
}, 0);

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

*Output:*

```plaintext
Start
End
Timer finished
```

* * *

### ❊ Step-by-Step Execution

Step 1

```javascript
console.log("Start")
```

Executed immediately.

Step 2

```javascript
setTimeout(...)
```

Timer is handled by **libuv timers system**.

Callback waits in queue.

Step 3

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

Runs immediately.

Step 4

Timer finishes → callback enters queue.

Step 5

Event loop pushes callback to stack.

```javascript
Timer finished
```

### ❊ Event Loop Phases (Advanced)

Node.js Event Loop has multiple phases.

Order:

```plaintext
1 Timers
2 Pending Callbacks
3 Idle / Prepare
4 Poll
5 Check
6 Close Callbacks
```

Examples:

```plaintext
setTimeout → Timers phase
I/O callbacks → Poll phase
setImmediate → Check phase
```

This is how Node.js schedules asynchronous work efficiently.

### ❊ Complete Node.js Architecture

Here is the complete flow:

```plaintext
Your JavaScript Code
        ↓
V8 Engine executes synchronous code
        ↓
Async operations detected
        ↓
libuv handles background tasks
        ↓
Callbacks added to queues
        ↓
Event Loop picks them
        ↓
Callback executed by V8
```

* * *

### ❊ Real-World Analogy (Restaurant System)

Imagine a restaurant.

![](https://cdn.hashnode.com/uploads/covers/656ed88ac1f28c5dd219df1a/342ddea9-01ae-40d5-8d27-79da034964a5.png align="center")

Actors:

```plaintext
Restaurant → Node.js Runtime
Waiter → Event Loop
Manager → V8 Engine
Chefs → libuv Threadpool
Customers → Users
Food Orders → JavaScript Tasks
```

Workflow:

1️⃣ Customer places order  
  
2️⃣ Waiter forwards order to chefs  
  
3️⃣ Chefs cook food in kitchen  
  
4️⃣ Waiter serves when ready

The waiter **never cooks**.

Similarly:

```plaintext
Event Loop does NOT execute code
V8 executes the code
```

The event loop simply **manages tasks**.

* * *

### ❊ Conclusion

Whenever you run Node.js, remember this pipeline:

```plaintext
JavaScript Code
       ↓
V8 Engine executes code
       ↓
Async tasks sent to libuv
       ↓
Callbacks stored in queues
       ↓
Event Loop pushes callbacks
       ↓
V8 executes them
```

This architecture is the reason Node.js can handle **thousands of concurrent connections efficiently**.

* * *

### **❊ Want More…?**

I write articles on [**blog.prakashtsx.com**](http://blog.prakashtsx.com) and also post development-related content on the following platforms:

*   [**Twitter/X**](https://x.com/prakashtsx)
    
*   [**LinkedIn**](https://www.linkedin.com/in/prakashtsx)
