Skip to main content

Command Palette

Search for a command to run...

How Node.js Actually Works

Event Loop, V8 Engine, and libuv Explained (Beginner → Advanced)

Published
6 min read
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:

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:


2. Understanding Runtime with a Simple Analogy

Similarly:

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


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

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

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

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:

function greet() {
  sayHello();
}

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

greet();

Execution order:

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:

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

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:

Threadpool Size = 4 threads

These threads run heavy operations in the background.

Example:

Read File
Hash Password
Compress Data
Write File

These tasks are executed without blocking the main thread.

You can even change the threadpool size:

process.env.UV_THREADPOOL_SIZE = 8;

8. Event Loop – The Coordinator

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

It constantly checks:

Is the call stack empty?

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

❊ Simple Event Loop Flow

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

❊ Example to Understand Event Loop

console.log("Start");

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

console.log("End");

Output:

Start
End
Timer finished

❊ Step-by-Step Execution

Step 1

console.log("Start")

Executed immediately.

Step 2

setTimeout(...)

Timer is handled by libuv timers system.

Callback waits in queue.

Step 3

console.log("End")

Runs immediately.

Step 4

Timer finishes → callback enters queue.

Step 5

Event loop pushes callback to stack.

Timer finished

❊ Event Loop Phases (Advanced)

Node.js Event Loop has multiple phases.

Order:

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

Examples:

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:

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.

Actors:

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:

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:

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 and also post development-related content on the following platforms: