Stop 02 · Node.js FundamentalsTopics · 3/18

Event Loop

Part of the Backend Developer Roadmap

In short

Node runs your JavaScript on one thread, yet a single server juggles thousands of connections. The event loop is how, and it decides the exact order your callbacks run in.

The mechanism that lets single-threaded Node.js handle thousands of concurrent connections by delegating I/O work and processing callbacks as they complete, instead of blocking.

The mascot walks a circle around three coloured baskets, picking up one slip at a time.

Think of it like this

The single cashier's rounds

One cashier, three baskets: 'due now', 'replies received', 'do right after'. She goes round them in the same order, one slip at a time. Urgent slips are handled the moment she finishes the current one, before she moves on. That round is the event loop.

Watch it happen

One turn of the event loop

Main script
Timers
Poll (I/O)
Check
Close

1/7Your script runs top to bottom first. setTimeout, setImmediate and fs calls only schedule work for later.

The big ideas

What you need to know

One thread for callbacks

Only one callback runs at a time. A long synchronous loop freezes every other request until it finishes.

Microtasks jump the queue

process.nextTick and promise callbacks run before the loop moves to its next phase.

0 ms doesn't mean now

setTimeout(fn, 0) runs on a later turn of the loop, after the current code and all microtasks.

The loop knows when to stop

When no timers, sockets or pending I/O are left, the loop ends and the process exits.

See it in code

Walk through the code

js
1// order.cjs  (run: node order.cjs)2const fs = require("node:fs");3 4console.log("1 sync");5setTimeout(() => console.log("timeout"), 0);6setImmediate(() => console.log("immediate"));7Promise.resolve().then(() => console.log("3 promise"));8process.nextTick(() => console.log("2 nextTick"));9 10fs.readFile(__filename, () => {11  setTimeout(() => console.log("io: timeout"), 0);12  setImmediate(() => console.log("io: immediate")); // always first here13});

1/4Synchronous code always runs first, before any callback.

Output starts 1 sync, 2 nextTick, 3 promise. At the top level, timeout and immediate may swap between runs; inside an I/O callback, setImmediate always wins.

Save yourself the pain

Common mistakes

Oops

Running a heavy loop, like hashing a million strings, inside a request handler.

Do this instead

That blocks the loop and every user waits. Move heavy CPU work to worker_threads or a background job queue.

Oops

Using setTimeout(fn, 0) expecting fn to run immediately.

Do this instead

It runs on a later turn. If you need it right after the current code, use queueMicrotask, or just call the function.

Your mission

Predict the order

~15 min

Quick check

In a CommonJS file, a resolved Promise's .then and a process.nextTick are both scheduled in the main script. Which logs first?

Go deeper

  1. 1Log the order of `setTimeout`, `Promise.then` and synchronous code to see the event loop phases.
  2. 2Learn the difference between the microtask queue (Promises) and macrotask queue (setTimeout).
  3. 3Understand why a long synchronous computation blocks the entire event loop.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge