Blocking I/O stops the calling thread until the operation finishes; non-blocking I/O returns immediately and lets the thread do other work while the operation completes. Sync vs async describes the same idea at the API level.
Blocking I/O stops the calling thread until the operation finishes; non-blocking I/O returns immediately and lets the thread do other work while the operation completes. Sync vs async describes the same idea at the API level.
read() until data arrives. Simple, but the thread is idle the whole time — to serve N slow clients you need N threads.Blocking: ──[ wait for disk ]── (thread stuck, does nothing)
Non-blocking: ──▶ returns now; event loop notified when ready
// Blocking: nothing else runs until the file is read
const data = fs.readFileSync('big.txt');
// Non-blocking: thread keeps going; callback fires later
fs.readFile('big.txt', (err, data) => { /* handle later */ });
// or async/await on top of non-blocking primitives
const data2 = await fs.promises.readFile('big.txt');
This is the core of scalable servers. Node.js and nginx handle huge connection counts on few threads precisely because I/O is non-blocking — waiting doesn't tie up a thread. Use blocking calls for simplicity in scripts; use non-blocking for high-concurrency network services, and never block the event loop with CPU-heavy work.
A library of IT interview questions with detailed answers — from Junior to Senior.
Donate