Skip to main content

Command Palette

Search for a command to run...

Blocking vs Non-Blocking Code in Node.js

Updated
3 min read
Blocking vs Non-Blocking Code in Node.js
V
Blog on different tools and technology or concept that useful for the begineer that start their jouney in software industry

When building backend applications, one of the most important concepts to understand is how your server handles multiple requests.

Should it wait for one task to finish?
Or should it move forward and handle other tasks?

This is where blocking and non-blocking code come into play.


What is Blocking Code?

Blocking code means the program waits for a task to complete before moving to the next one.

The execution is paused until the operation finishes.

Example:

const fs = require('fs');

const data = fs.readFileSync('file.txt', 'utf-8');
console.log(data);

console.log("Next line");

Here:

  • The server waits until the file is fully read

  • Only then it moves to the next line


What is Non-Blocking Code?

Non-blocking code allows the program to start a task and move on without waiting.

The result is handled later using callbacks, promises, or async/await.

Example:

const fs = require('fs');

fs.readFile('file.txt', 'utf-8', (err, data) => {
    console.log(data);
});

console.log("Next line");

Here:

  • File reading starts

  • Program continues execution immediately

  • Result comes later


Waiting vs Continuing

Imagine you're cooking:

❌ Blocking:

  • You put water to boil

  • You stand there and wait

  • Do nothing else


Non-Blocking:

  • You put water to boil

  • You start cutting vegetables

  • Come back when water is ready

Node.js follows the second approach.


Why Blocking Slows Down Servers

In a server:

  • Multiple users send requests at the same time

  • If one request blocks the server → others must wait

Result:

  • Slow response time

  • Poor user experience

  • Reduced scalability

Example Scenario:


How Node.js Handles Async Operations

Node.js uses:

  • Non-blocking I/O

  • Event loop

Flow:

This allows Node.js to handle thousands of requests efficiently.


Real-World Example: File Handling

❌ Blocking Version

const fs = require('fs');

app.get('/data', (req, res) => {
    const data = fs.readFileSync('bigfile.txt', 'utf-8');
    res.send(data);
});

Problem:

  • Server waits for file to load

  • Other requests get blocked


Non-Blocking Version

const fs = require('fs');

app.get('/data', (req, res) => {
    fs.readFile('bigfile.txt', 'utf-8', (err, data) => {
        res.send(data);
    });
});

Benefit:

  • Server continues handling other requests

  • Faster overall performance


Real-World Example: Database Call

❌ Blocking Thinking (Bad Approach)

  • Wait for DB response

  • Freeze execution


Non-Blocking (Actual Node.js Style)

app.get('/users', async (req, res) => {
    const users = await db.getUsers(); // async
    res.json(users);
});

While waiting:

  • Node.js handles other requests

  • No blocking happens


Quick Comparison

Feature Blocking Code Non-Blocking Code
Execution Waits Continues
Performance Slow Fast
Scalability Poor High
Use Case Rare Preferred in Node.js

Conclusion

Understanding blocking vs non-blocking code is essential for writing efficient Node.js applications.

By using non-blocking operations, you can build servers that are fast, scalable, and capable of handling multiple users at the same time.