Skip to main content

Command Palette

Search for a command to run...

Blocking vs Non-Blocking Code in Node.js

Updated
6 min read
N

I build clean and simple web experiences and learn something new every day.

When I first started learning Node.js…

I kept hearing this sentence everywhere: “Node.js is non-blocking.”

And honestly… initially I had NO idea what that actually meant.

Like…
What exactly is being blocked?
And why is “non-blocking” considered such a big deal?

Then one day I compared two file-reading examples side by side… and suddenly everything clicked.

Because the difference between:

Blocking

and

Non-Blocking

is basically the difference between: waiting vs continuing work
And that single idea is one of the biggest reasons Node.js became so popular.


First Important Understanding

Programs constantly perform tasks that take time.

Examples:

  • reading files

  • database queries

  • API requests

  • network calls

These operations are NOT instant.
So the real question becomes: what should server do while waiting?


Blocking Code

Blocking code means: execution STOPS until task finishes.

Nothing else moves forward.


Simple Mental Model

Start Task
    ↓
WAIT...
    ↓
Task Finishes
    ↓
Continue Execution

Everything pauses in the middle.


Real-Life Analogy

Imagine you’re cooking noodles.

Blocking behavior would be: standing in front of boiling water for 10 minutes doing absolutely nothing else.

No multitasking.
No other work.
Just waiting.

That’s blocking.


Blocking File Example

const fs = require("fs");

const data = fs.readFileSync("demo.txt", "utf8");

console.log(data);

console.log("Finished");

What Happens Here?

This line:

fs.readFileSync()

is synchronous.

Meaning: Node.js WAITS until file fully loads.

Only after reading completes:

console.log("Finished")

executes.


Visual Timeline

Read File
   ↓
WAIT...
   ↓
File Loaded
   ↓
Continue Code

The application gets stuck during waiting period. That’s blocking behavior.


Why Blocking Is Dangerous for Servers

Now imagine: 1000 users hit your server. And server blocks for every request.

What happens?

requests pile up
users wait longer
application slows badly

That’s why blocking operations become dangerous in backend systems.


Another Important Realization

Initially blocking feels “normal.”

Because beginners are used to:

Line 1
Line 2
Line 3

executing strictly in order. But servers handling many users need smarter execution models.

That’s where:

Non-Blocking Code

comes in.


What Is Non-Blocking Code?

Non-blocking means: start task WITHOUT stopping entire application.

Instead of waiting…
Node.js continues doing other work.


Simple Mental Model

Start Task
    ↓
Continue Other Work
    ↓
Task Finishes Later
    ↓
Handle Result

That’s the core idea.


Non-Blocking File Example

const fs = require("fs");

fs.readFile("demo.txt", "utf8", (err, data) => {
  console.log(data);
});

console.log("Finished");

Output

Finished
[file content later]

And honestly… this execution order confused me SO much initially.

Because: code below executed BEFORE file finished loading.


What’s Actually Happening?

Node.js says: “Start reading file.”

Then immediately continues running next code.

Meanwhile: file reading happens asynchronously.

When task finishes: callback executes later.


Visual Flow

File Reading Starts
        ↓
Node.js Continues Running
        ↓
File Finishes Later
        ↓
Callback Executes

This is non-blocking execution.


Why This Is Powerful

Because waiting time becomes useful time. Instead of freezing during slow operations…

Node.js keeps handling:

  • more users

  • more requests

  • more tasks

That efficiency is HUGE for scalability.


Another Real-Life Analogy

Imagine restaurant waiter.


Blocking Waiter

Waiter takes one order. Then stands inside kitchen staring at food cooking.

Meanwhile: ignores all other customers.

Terrible system.


Non-Blocking Waiter (Node.js Style)

Waiter places order in kitchen.

Then immediately:

  • serves other tables

  • takes new orders

  • handles payments

That’s non-blocking behavior.


Sync vs Async

You’ll often hear these terms too.


Synchronous

Usually means: blocking execution.

Example:

readFileSync()

Asynchronous

Usually means: non-blocking execution.

Example:

readFile()

Important Insight

Non-blocking doesn’t mean: task finished instantly.

It means: application didn’t stop while waiting.

That distinction matters A LOT.


Database Example

Imagine database takes:

3 seconds

to respond.


Blocking Server

Request Comes
     ↓
WAIT 3 Seconds
     ↓
Next Request Starts

Slow.


Non-Blocking Server

Request Comes
     ↓
Database Task Starts
     ↓
Server Handles Other Requests
     ↓
DB Response Returns Later

Much more efficient.


This non-blocking architecture made Node.js amazing for:

  • APIs

  • chat apps

  • streaming

  • real-time dashboards

  • multiplayer systems

Because these apps constantly deal with: waiting on I/O operations.

And Node.js handles waiting VERY efficiently.


Small But Powerful Realization

At first I thought Node.js was fast because JavaScript is fast.

But later I realized: the architecture matters more than raw language speed.

Avoiding blocking is the real superpower.


Common Beginner Mistake

Many beginners accidentally use blocking methods in servers.

Example:

readFileSync()

inside API routes. This can freeze request handling under heavy traffic. That’s why async methods are usually preferred in backend apps.


Another Important Understanding

Non-blocking does NOT mean infinite performance. CPU-heavy tasks can STILL block Node.js.

Example:

  • huge loops

  • video processing

  • heavy calculations

These can occupy main thread badly.

Non-blocking mainly helps with: I/O operations.


Blocking vs Non-Blocking Comparison


Blocking

Wait for task
Execution pauses
Slower scalability

Non-Blocking

Continue execution
Handle tasks later
Better concurrency

Why This Matters in Real Servers

Imagine thousands of users opening app simultaneously. If every request blocks server…
performance collapses quickly. Non-blocking systems help Node.js stay responsive even under heavy traffic.

That’s one reason Node.js became so widely adopted.


Another Interesting Insight

The event loop plays a huge role here too.

Because Node.js uses:

  • async callbacks

  • task queues

  • event loop scheduling

to manage non-blocking execution efficiently. Everything connects together.


Visual Comparison

Blocking

Task Starts
    ↓
WAIT...
    ↓
Continue

Non-Blocking

Task Starts
    ↓
Continue Other Work
    ↓
Task Finishes Later

That difference changes everything.


Assignment Practice

Try these yourself:

1. Use readFileSync()
2. Use readFile()
3. Compare output order
4. Add multiple requests
5. Observe blocking behavior carefully

That comparison teaches Node.js architecture REALLY well.


Final Understanding

At first, blocking vs non-blocking sounds like technical jargon. But underneath everything…

the idea is actually simple:

blocking code waits
non-blocking code keeps moving

And honestly…

this non-blocking philosophy is one of the biggest reasons Node.js handles modern web applications so efficiently.

More from this blog

C

codeXninjaDev

54 posts

I build clean and simple web experiences and learn something new every day.