Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
A blocking system call is a hard stop: your thread sits frozen in kernel space until the OS has data, burning CPU scheduling overhead while producing nothing. For an API handler waiting 50ms for a database query, that's 50ms of thread-time charged to a single request — and under load that means you need one OS thread per concurrent request, which collapses at scale. A non-blocking alternative returns immediately and an event notification (epoll, kqueue, IOCP) fires when the fd is ready — freeing the thread to serve other requests in the meantime. This is the foundation of every high-concurrency server built in the last 20 years, from nginx to Node.js to Tokio: a handful of threads can multiplex thousands of in-flight network operations because none of them block.
When you call read(fd) synchronously, your thread sits frozen in kernel-space until bytes arrive. If that takes 200 ms, 200 ms of thread-time is gone.
A non-blocking equivalent returns immediately (either with data or with "not yet"), freeing the thread to do something else. An event loop (epoll / kqueue / IOCP) then tells you when the fd is ready. This is the foundation of every high-concurrency server.
execSync in Node) and observe the change.Use these three in order. Each builds on the one before.
Explain what 'blocking' and 'non-blocking' mean at the system-call level. What does the thread actually do in each case?
How do epoll (Linux), kqueue (BSD/macOS), and IOCP (Windows) let a single thread watch thousands of file descriptors without blocking?
If my Node.js server calls `fs.readFileSync` inside a request handler, explain exactly what breaks and how to measure the impact on p99 latency.
// main.js — non-blocking HTTP fetch; the thread is free to do other work
const started = Date.now();
fetch("https://httpbin.org/delay/1")
.then((r) => r.text())
.then(() => console.log("fetch done at", Date.now() - started, "ms"));
// This log runs BEFORE the fetch completes — the thread didn't block.
console.log("doing other work at", Date.now() - started, "ms");node main.js