Blocking vs Non-Blocking
Overview
Because Node.js executes JavaScript on a single thread, performance is entirely dictated by how you handle Slow Operations (like reading a 5GB video file from a hard drive). If you use a 'Blocking' (Synchronous) method, the V8 engine physically halts, refusing to run any other JavaScript until the hard drive finishes. If you use a 'Non-Blocking' (Asynchronous) method, V8 delegates the file read to libuv in the background, and instantly moves on to serve other users.
Syntax
const fs = require('fs');
// --- 1. BLOCKING (Synchronous) - FATAL FOR SERVERS ---
console.log("1. Starting");
// The entire Node.js server FREEZES on this line.
// No other user can log in or make API requests until this finishes.
const data = fs.readFileSync('massive_file.txt', 'utf8');
console.log("2. Finished reading");
// --- 2. NON-BLOCKING (Asynchronous) - THE NODE.JS WAY ---
console.log("1. Starting");
// Node hands the task to the background Thread Pool and INSTANTLY moves on!
fs.readFile('massive_file.txt', 'utf8', (err, data) => {
// This callback fires whenever the background thread is done.
console.log("3. Finished reading");
});
console.log("2. Moving on to serve other users immediately!");Common Pitfalls
- Using
Syncmethods in an Express API route. If you usefs.readFileSyncorbcrypt.hashSyncinside an API endpoint, you have created a massive bottleneck. If 100 users hit that endpoint, User 100 has to wait for Users 1 through 99 to completely finish their file reads before the server even acknowledges them. - Assuming Non-Blocking means 'Parallel JavaScript'. Node does not run your JS code in parallel. It runs the I/O (Input/Output) in parallel via the OS, but your JS callbacks are still executed sequentially on the single main thread.
Interview Questions
readFileSync?Synchronous methods are perfectly acceptable (and often preferred for readability) when writing one-off CLI scripts (like a build step in Webpack) or during the initial startup phase of a server (like reading a config file before the server starts accepting HTTP traffic).
Real-World Example
How modern Node uses Promises (Async/Await) to make Non-Blocking code look incredibly clean.
const fs = require('fs/promises'); // Import the modern Promise-based version!
async function getConfigFile() {
try {
// NON-BLOCKING! The server doesn't freeze.
// V8 just pauses this specific function and goes to do other work.
const data = await fs.readFile('config.json', 'utf8');
return JSON.parse(data);
} catch (err) {
console.error("Failed to read file", err);
}
}Check Your Knowledge
Test your understanding of Blocking vs Non-Blocking with these quick questions.