How Node.js Actually Works
Event Loop, V8 Engine, and libuv Explained (Beginner → Advanced)

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:
V8 Engine – executes JavaScript
libuv – handles asynchronous operations
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
Parsing: JavaScript is parsed into an AST.
Ignition (Interpreter): Executes unoptimized bytecode quickly.
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:



