Chapter 6: Node.js Architecture

Node.js Architecture — written as if we are sitting together with a whiteboard, drawing layers, arrows, and boxes while I explain how everything actually fits together in 2025–2026.

I will try to make it very visual in text form, very concrete, and I will show the most important concepts with small code examples where it helps understanding.

1. The Big Picture – One clear layered diagram

text

Four major layers (from top to bottom):

  1. Your Application Code (what you write)
  2. V8 JavaScript Engine (executes your JS)
  3. Node.js Core (C++ + JavaScript glue code)
  4. libuv + lower-level libraries (OS-level I/O, threads, networking…)

2. Layer by layer – detailed explanation

Layer 1 – Your JavaScript Code

This is what you actually write:

JavaScript

Everything here runs single-threaded inside one V8 instance.

Layer 2 – V8 Engine

Responsible for:

  • Parsing your JavaScript
  • Compiling to bytecode
  • Optimizing hot functions (TurboFan)
  • Managing memory (Orinoco garbage collector)
  • Executing your synchronous code + calling async callbacks

Important facts 2025–2026:

  • One V8 instance per Node.js process (unless using Worker Threads)
  • Single JavaScript thread per process
  • Very good at optimizing predictable code
  • Very bad at long synchronous CPU work

Layer 3 – Node.js Core (the “glue”)

Written mostly in C++, with some JavaScript.

This layer does two crucial jobs:

  1. Exposes C++ functionality to JavaScript (http parser, file system, crypto, zlib, dns, tls…)
  2. Integrates libuv into V8’s event loop

Most important built-in modules come from here:

  • fs (file system)
  • http / https
  • net (TCP sockets)
  • stream
  • crypto
  • zlib
  • events
  • buffer
  • process
  • child_process

Example: when you write

JavaScript

→ Node.js core forwards this call to libuv

Layer 4 – libuv (the real magic of Node.js)

libuv is a C library that provides:

  • Event loop (the heart)
  • Asynchronous I/O operations
  • Thread pool for blocking tasks
  • Cross-platform abstractions (Windows IOCP, Linux epoll/kqueue, etc.)

libuv has four main responsibilities in Node.js:

Responsibility Handled by libuv? Examples Thread?
Timers Yes setTimeout, setInterval, setImmediate Main thread
I/O polling (network) Yes Incoming HTTP requests, TCP/UDP Main thread
File system operations Yes readFile, writeFile, readdir Thread pool
DNS lookups Yes dns.lookup, getaddrinfo Thread pool
CPU-intensive crypto Yes crypto.pbkdf2, crypto.scrypt Thread pool
Child process spawning Yes spawn, fork, exec Separate
Signal handling Yes SIGINT, SIGTERM Main thread

Key insight:

Most blocking operating system calls are offloaded to a thread pool → so your JavaScript thread (event loop) stays free to handle other requests

Default thread pool size = 4 threads

You can change it:

Bash

or in code:

JavaScript

3. How the Event Loop actually works (simplified but accurate)

text

Very important order in real applications:

  1. Timers (setTimeout, setInterval)
  2. I/O callbacks (network reads/writes, file reads…)
  3. setImmediate
  4. Close events

Classic interview / debugging question:

JavaScript

Answer: It depends — but in practice setImmediate often wins on Windows/Linux when run from I/O phase.

4. Summary table – Node.js Architecture at a glance

Layer / Component Language Main responsibility Single-threaded? Can block event loop?
Your application code JavaScript Business logic, routing, async flows Yes Yes (if sync CPU work)
V8 Engine C++ Parse, compile, optimize & execute JS Yes Yes
Node.js Core bindings C++ + JS Connect JS ↔ libuv / native libraries Yes No (delegates)
libuv – Event Loop C Orchestrates timers, I/O polling Yes No
libuv – Thread Pool C File system, DNS, some crypto No (4+ threads) No (offloaded)
Operating System Real networking, file system, threads

5. Quick real-world implications

Situation What happens in Node.js architecture Recommendation / Fix
Long synchronous for-loop (10 seconds) Blocks entire event loop → server freezes Use Worker Threads or break into setImmediate
Reading 1000 small files Goes to thread pool → usually fine Increase UV_THREADPOOL_SIZE if bottleneck
Handling 10,000 concurrent requests Event loop stays responsive (I/O is async) Good – this is Node’s strength
Heavy image processing in route handler Blocks event loop → very bad Offload to worker thread or external service
Doing crypto.pbkdf2 10,000 times Uses thread pool → acceptable Still better to batch or offload if possible

Would you like to go deeper into any specific part?

Popular next topics people usually ask after this:

  • Detailed walkthrough of one full event loop tick with real code
  • How Worker Threads fit into this architecture
  • What happens when you do cluster.fork()
  • How streams interact with libuv
  • Common performance bottlenecks seen in production
  • Comparison: Node.js architecture vs Go / Java / Rust / Bun

Just tell me which direction feels most useful — I’ll continue with drawings, code, and concrete examples. 😄

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *