This article explains how Node.js processes asynchronous code by tracing the path from V8 engine through the event loop, microtasks, and libuv.
Node.js runs JavaScript outside the browser. It relies on the V8 engine to compile code. V8 turns source into machine instructions that the processor executes.
V8 manages memory with a heap and a call stack. The call stack tracks function entry and exit. The heap stores objects and strings.
A function finishes and the call stack pops it. Synchronous code runs to completion before anything else moves. Asynchronous work such as timers or file reads hands off to libuv.
Libuv provides a thread pool for heavy operations. It moves the task to a background thread and signals completion via an event. The event goes into a queue that the event loop monitors.
The event loop runs through several phases. It handles timers and I/O callbacks. It also manages idle work before polling for new events.

Microtasks include promise resolutions and queueMicrotask calls. They run after the current operation finishes and before the event loop advances. Macrotasks such as setTimeout or setImmediate wait for a full loop turn.
Consider a file read with fs.readFile. Node.js calls libuv, which uses a thread pool to read the disk. The read ends and libuv places a callback in the poll queue. The event loop picks up the callback. It runs the callback and returns control to V8.
You gain insight that helps you debug performance issues and design non‑blocking APIs. You can see why heavy computation blocks the event loop while I/O runs in parallel.

Comments
Please log in or register to join the discussion