How Node.js Works — V8, libuv & the Runtime
Node.js is NOT just JavaScript on the server. It is a C++ application that embeds the V8 JavaScript engine and pairs it with libuv — a cross-platform async I/O library. Understanding this architecture explains why Node.js is single-threaded yet can handle thousands of concurrent connections.
The Three Pillars
- **V8 Engine**: Compiles JavaScript to native machine code using JIT compilation. Manages the JS heap and garbage collection. Executes your JS code single-threaded
- **libuv**: A C library providing the event loop, a thread pool (4 threads by default, configurable via UV_THREADPOOL_SIZE), and async I/O wrappers for file system, DNS, and crypto
- **Node.js C++ Bindings**: Bridge between JavaScript and the OS. When you call fs.readFile(), JS calls a C++ binding which calls libuv which talks to the OS using epoll (Linux), kqueue (macOS), or IOCP (Windows)
- **The key insight**: JavaScript execution is single-threaded. But libuv offloads blocking work to a thread pool. So Node.js is concurrent without being multi-threaded in JS
Architecture Flow
// What happens when you call fs.readFile():
import { readFile } from 'fs/promises';
const data = await readFile('./huge-file.txt'); // non-blocking
// 1. JS code calls fs.readFile (JS land)
// 2. Node.js C++ binding receives the call
// 3. libuv adds the I/O operation to the thread pool queue
// 4. A libuv thread opens the file and reads from the OS
// 5. While that thread is reading, the event loop runs other callbacks
// 6. When the OS finishes, libuv puts the result in the event queue
// 7. Event loop picks it up on the next I/O poll phase
// 8. Your promise resolves in JS land
// Thread pool size — default 4, max 1024
// Increase for CPU-intensive or heavy I/O workloads:
// UV_THREADPOOL_SIZE=16 node server.jsTip
Tip
Node.js is not a framework — it's a runtime. Think of it as JavaScript without the browser. The event loop is the core concept to master: understanding how async code is scheduled will make you a significantly better Node.js developer.
Node is single-threaded for JS but uses multiple threads for I/O
Practice Task
Note
Practice Task — (1) Create a simple Node.js script that reads a file and logs its contents. (2) Convert it to use async/await. (3) Add error handling for when the file doesn't exist.
Quick Quiz
Common Mistake
Warning
Node.js is not a framework — it's a runtime. Think of it as JavaScript without the browser. The event loop is the core concept to master: understanding how async code is scheduled will make you a significantly better Node.js developer.
Key Takeaways
- *V8 Engine**: Compiles JavaScript to native machine code using JIT compilation. Manages the JS heap and garbage collection. Executes your JS code single-threaded
- *libuv**: A C library providing the event loop, a thread pool (4 threads by default, configurable via UV_THREADPOOL_SIZE), and async I/O wrappers for file system, DNS, and crypto
- *Node.js C++ Bindings**: Bridge between JavaScript and the OS. When you call fs.readFile(), JS calls a C++ binding which calls libuv which talks to the OS using epoll (Linux), kqueue (macOS), or IOCP (Windows)