Blocking vs Non-Blocking Code in Node.js
What is Blocking Code?
Blocking code is code that stops the execution of further operations until the current task finishes.
In simple words:
“Wait here until this work is complete.”
During this time, Node.js cannot continue executing the next line or handle other incoming requests.
Example of Blocking Code
const fs = require("fs");
console.log("Start");
const data = fs.readFileSync("data.txt", "utf-8");
console.log(data);
console.log("End");
Output
Start
(file content)
End
What Happens Internally?
The readFileSync() method is synchronous.
Node.js:
Starts reading the file
Waits until the file is fully read
Then moves to the next line
Until the file operation finishes, the entire thread is blocked.
Why Blocking Code is Bad for Servers
Node.js uses a single-threaded event loop to handle requests.
If one request runs blocking code:
Other requests must wait
Server response time increases
Performance drops under heavy traffic
Imagine:
User A uploads a huge file
Server uses blocking file read
User B and User C must wait
This creates a bottleneck.
What is Non-Blocking Code?
Non-blocking code allows Node.js to start a task and continue executing other operations without waiting.
Instead of pausing execution, Node.js delegates the operation to the system and continues handling other work.
When the task finishes, a callback, promise, or async function handles the result.
Example of Non-Blocking Code
const fs = require("fs");
console.log("Start");
fs.readFile("data.txt", "utf-8", (err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data);
});
console.log("End");
Output
Start
End
(file content)
How Node.js Handles Async Operations
Node.js uses:
Event Loop
Callback Queue
Worker Threads (via libuv)
When an async task starts:
Node delegates heavy operations like:
File system access
Database queries
Network requests
The main thread remains free
Once completed, the result returns to the event loop
This architecture makes Node.js highly scalable.
Real-World Example: File Reading
Blocking File Read
const fs = require("fs");
const data = fs.readFileSync("largeFile.txt", "utf-8");
console.log(data);
Problem:
Server waits until the file is fully read
Other users may experience delays
Non-Blocking File Read
const fs = require("fs");
fs.readFile("largeFile.txt", "utf-8", (err, data) => {
if (err) throw err;
console.log(data);
});
Benefit:
Server continues handling requests
Better responsiveness

