Skip to main content

Command Palette

Search for a command to run...

Blocking vs Non-Blocking Code in Node.js

Updated
6 min read
Blocking vs Non-Blocking Code in Node.js

One of the biggest reasons Node.js became popular is its ability to handle many requests efficiently.

This happens because Node.js heavily relies on:

Non-blocking code

To understand Node.js properly, you must understand the difference between:

  • blocking code

  • non-blocking code

In this article, we’ll learn:

  • What blocking code means

  • What non-blocking code means

  • Why blocking slows servers

  • Async operations in Node.js

  • Real-world examples like file reading and database calls

Let’s begin.


What Does “Blocking” Mean?

Blocking means:

The program must wait before moving to the next task

Execution stops until the current task finishes.


Simple Real-Life Analogy

Imagine ordering food at a restaurant.


Blocking Behavior

The waiter:

  • takes one order

  • waits for food to finish

  • then takes the next order

Other customers must wait.


Non-Blocking Behavior

The waiter:

  • takes one order

  • sends it to kitchen

  • immediately handles next customer

This is much more efficient.

Node.js follows this second approach.


Understanding Blocking Code

Blocking code prevents other operations from executing until completion.


Blocking Execution Timeline

Task 1 Running
      ↓
Wait Until Complete
      ↓
Task 2 Starts
      ↓
Task 3 Starts

Everything waits in sequence.


Blocking File Read Example

Node.js provides synchronous methods that block execution.

Example:

const fs = require("fs");

const data = fs.readFileSync("test.txt", "utf-8");

console.log(data);

console.log("Finished");

What Happens Here?

Flow:

Read File
    ↓
Wait Until File Fully Loaded
    ↓
Print Data
    ↓
Continue Execution

The server cannot continue until file reading completes.


Why Blocking Is Bad for Servers

Imagine thousands of users accessing a server.

If one request blocks the server:

Other requests must wait

This reduces:

  • performance

  • scalability

  • responsiveness


What Is Non-Blocking Code?

Non-blocking code allows the program to:

Continue executing while tasks run in background

Node.js heavily uses this model.


Non-Blocking Execution Timeline

Task 1 Starts
Task 2 Starts
Task 3 Starts
      ↓
Results Return Later

Execution keeps moving.


Non-Blocking File Read Example

Example:

const fs = require("fs");

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

console.log("Finished");

Understanding the Execution Flow

Flow:

Start File Read
       ↓
Continue Execution
       ↓
Print "Finished"
       ↓
File Data Returns Later

Node.js does not wait for the file operation to complete.


Output Order

Output may look like:

Finished
File Content Here

because file reading happens asynchronously.


Why Node.js Uses Non-Blocking I/O

I/O means:

Input / Output Operations

Examples:

  • file reading

  • database queries

  • API requests

  • network communication

These operations take time.

Node.js avoids waiting unnecessarily.


Async Operations in Node.js

Node.js delegates slow tasks to:

Background system workers

while the main thread continues handling requests.


Event Loop Role

The event loop checks for completed operations and executes callbacks when tasks finish.


Event Loop Flow

Request Arrives
       ↓
Async Task Delegated
       ↓
Node.js Handles Other Requests
       ↓
Task Completes
       ↓
Callback Executes

This is the core of Node.js scalability.


Real-World Example: Database Calls

Database queries are usually slow compared to normal code execution.


Blocking Database Flow

Query Database
      ↓
Wait
      ↓
Continue

Server becomes idle while waiting.


Non-Blocking Database Flow

Send Query
     ↓
Handle Other Requests
     ↓
Database Responds Later

Much more efficient.


Why Non-Blocking Improves Performance

Non-blocking systems can:

✅ Handle more users ✅ Process more requests ✅ Improve responsiveness ✅ Avoid server idle time

This is why Node.js works very well for:

  • APIs

  • chat applications

  • streaming systems

  • real-time applications


Blocking vs Non-Blocking Comparison

Blocking Non-Blocking
Waits for task completion Continues execution
Slower for many requests Better scalability
Sequential execution Async execution
Can freeze server Keeps server responsive

Synchronous vs Asynchronous

Blocking often relates to:

Synchronous execution

Non-blocking usually relates to:

Asynchronous execution

Though they are closely related, they are not always identical concepts.


Common Async Operations in Node.js

Examples include:

  • file handling

  • database queries

  • API calls

  • timers

  • authentication requests

Most backend systems rely heavily on async behavior.


Real-World Scenario

Imagine a social media application.

Thousands of users may:

  • upload posts

  • fetch notifications

  • load feeds

If the server blocked for every request:

Performance would collapse

Non-blocking architecture helps Node.js scale efficiently.


Common Beginner Misconceptions

Non-Blocking Means Multiple Threads

Not exactly.

Node.js primarily uses:

A single JavaScript thread

with asynchronous task delegation.


Async Code Runs Instantly

Async tasks still take time.

Node.js simply avoids waiting during that time.


Blocking Is Always Bad

Blocking code can still be useful for:

  • small scripts

  • startup configuration

  • quick utilities

But not ideal for high-traffic servers.


Practice Assignment

Try these exercises yourself.


1. Use readFileSync()

Observe blocking behavior.


2. Use readFile()

Observe asynchronous behavior.


3. Compare Output Order

Experiment with:

console.log()

before and after async operations.


4. Add setTimeout()

Observe how Node.js handles delayed execution.

Example:

setTimeout(() => {
  console.log("Done");
}, 2000);

5. Think About Real APIs

Consider why asynchronous behavior matters for:

  • authentication

  • database access

  • external APIs


Final Thoughts

Understanding blocking vs non-blocking code is essential for backend development with Node.js.

The key idea is:

Blocking code waits.
Non-blocking code continues execution.

Node.js became powerful because it efficiently handles asynchronous operations using:

  • non-blocking I/O

  • event-driven architecture

  • the event loop

This allows Node.js applications to remain:

  • responsive

  • scalable

  • fast under heavy traffic

As you continue learning backend engineering, mastering asynchronous thinking will become one of your most important skills.


And now, you know the difference between blocking and non-blocking code in Node.js.

If you have any doubt or want to connect, feel free to drop a comment — I’d be happy to help.

Thanks for reading, and see you in the next blog!

Peace ✌️ and Happy Learning!