DEV Community

Sudhanshu code
Sudhanshu code

Posted on

From JavaScript to Node.js: Understanding What Really Happens Behind the Scenes (Part 2)

From JavaScript to Node.js: Understanding What Really Happens Behind the Scenes (Part 2)

What Actually Happens After You Run node app.js?

In the previous article, we answered one important question:

Why does Node.js exist?

Now we're going to answer a much deeper question.

What actually happens when you execute this command?

node app.js
Enter fullscreen mode Exit fullscreen mode

Most developers know that "Node executes JavaScript."

But that's only the surface.

Behind this simple command, thousands of lines of C++, operating system calls, memory allocation, and multiple software layers start working together.

Understanding this journey completely changed the way I think about backend development.

Let's follow that journey.


Step 1 — Your JavaScript File Is Just Text

Suppose your application looks like this:

console.log("Application Started");
Enter fullscreen mode Exit fullscreen mode

Before execution, app.js is nothing more than a text file stored on your SSD or HDD.

The computer does not see JavaScript.

It only sees bytes.

Imagine your file as:

Storage
│
├── app.js
│
└── Contains plain text characters
Enter fullscreen mode Exit fullscreen mode

Nothing has executed yet.


Step 2 — The Operating System Starts Node.js

When you type

node app.js
Enter fullscreen mode Exit fullscreen mode

your terminal doesn't magically understand JavaScript.

Instead, your operating system does something similar to this:

Windows / Linux / macOS

↓

Find node executable

↓

Create a new process

↓

Allocate memory

↓

Load Node.js into RAM

↓

Start execution
Enter fullscreen mode Exit fullscreen mode

This is extremely important.

The operating system starts Node.js first.

Node.js starts your JavaScript later.

Many beginners think:

JavaScript

↓

Node
Enter fullscreen mode Exit fullscreen mode

Reality is:

Operating System

↓

Node Process

↓

V8

↓

JavaScript
Enter fullscreen mode Exit fullscreen mode

What Is a Process?

A process is simply a running instance of a program.

Example:

Chrome.exe

↓

Running

↓

Chrome Process
Enter fullscreen mode Exit fullscreen mode

Similarly,

node app.js

↓

Running

↓

Node Process
Enter fullscreen mode Exit fullscreen mode

Every process has:

  • its own memory
  • its own call stack
  • its own heap
  • its own resources
  • its own execution context

This isolation is one reason why applications don't accidentally overwrite each other's memory.


Step 3 — Node Initializes the Runtime

After the process starts, Node initializes several internal systems.

These include:

  • V8 Engine
  • Memory
  • Event Loop
  • Timers
  • Internal Modules
  • libuv
  • Environment Variables
  • Process Object

Only after all of these are prepared does Node begin loading your JavaScript.


The Biggest Misconception About Node.js

Many developers imagine this:

JavaScript

↓

Node.js

↓

Computer
Enter fullscreen mode Exit fullscreen mode

This is incomplete.

The real architecture is much larger.

Your JavaScript
        │
        ▼
      V8 Engine
        │
        ▼
 Node.js APIs
        │
        ▼
 C++ Bindings
        │
        ▼
      libuv
        │
        ▼
Operating System
        │
        ▼
Hardware
Enter fullscreen mode Exit fullscreen mode

Every layer has a different responsibility.

Let's understand every one.


Layer 1 — V8 Engine

The V8 Engine is Google's open-source JavaScript engine.

Its responsibility is very small but extremely important.

It executes JavaScript.

Nothing more.

V8 understands:

  • Variables
  • Objects
  • Arrays
  • Functions
  • Classes
  • Loops
  • Promises
  • Closures
  • Arithmetic
  • Memory management
  • Garbage Collection

Example:

const a = 10;
const b = 20;

console.log(a + b);
Enter fullscreen mode Exit fullscreen mode

V8 can execute this entirely on its own.

No operating system interaction is required.


What V8 Cannot Do

Now consider this code.

const fs = require("fs");

fs.readFile("data.txt");
Enter fullscreen mode Exit fullscreen mode

Can V8 read files?

No.

Can V8 create an HTTP server?

No.

Can V8 open TCP sockets?

No.

Can V8 communicate with the operating system?

No.

This surprises many beginners.

V8 is not Node.js.

It is only a JavaScript engine.


Layer 2 — Node APIs

This is where Node becomes powerful.

Node provides JavaScript with additional capabilities.

Examples include:

fs

http

https

path

crypto

stream

dns

os

net

child_process
Enter fullscreen mode Exit fullscreen mode

These are called Node APIs or Node Core Modules.

They are not JavaScript language features.

They exist because Node adds them.

For example,

fs.readFile()
Enter fullscreen mode Exit fullscreen mode

is not part of JavaScript.

Node provides it.

Without Node,

this API doesn't exist.


Layer 3 — C++ Bindings

Now imagine this line.

fs.readFile("data.txt");
Enter fullscreen mode Exit fullscreen mode

JavaScript itself has absolutely no idea how to read a file.

Think about it.

How can JavaScript know:

  • where the file is stored?
  • which SSD sector contains it?
  • how Windows reads files?
  • how Linux reads files?

It can't.

So Node translates JavaScript into native code.

This translation layer is called C++ Bindings.

Think of it like a translator.

JavaScript

↓

"I want to read a file."

↓

C++

↓

Operating System understands.
Enter fullscreen mode Exit fullscreen mode

Node itself is largely written in C++.

These bindings connect JavaScript with native system functions.


Layer 4 — libuv

This is probably the most important component of Node.js.

And surprisingly...

many Node developers never learn what it actually is.

So what is libuv?

libuv is a cross-platform asynchronous I/O library written in C.

That definition sounds intimidating.

Let's simplify it.

Imagine Node directly talking to Windows.

Node

↓

Windows APIs
Enter fullscreen mode Exit fullscreen mode

Now imagine the same Node application running on Linux.

Linux has completely different system APIs.

Node would need separate implementations for:

  • Windows
  • Linux
  • macOS
  • BSD
  • Unix

That would be a maintenance nightmare.

Instead,

Node talks only to libuv.

Node

↓

libuv

↓

Windows
Enter fullscreen mode Exit fullscreen mode

or

Node

↓

libuv

↓

Linux
Enter fullscreen mode Exit fullscreen mode

or

Node

↓

libuv

↓

macOS
Enter fullscreen mode Exit fullscreen mode

libuv hides operating system differences.

Your JavaScript remains identical.


Layer 5 — Operating System

Now the request finally reaches the operating system.

Suppose your code is

fs.readFile("photo.png");
Enter fullscreen mode Exit fullscreen mode

The OS now becomes responsible for:

  • locating the file
  • checking permissions
  • communicating with the file system
  • requesting data from storage
  • returning the bytes

Node itself never searches your SSD.

The operating system does.


Layer 6 — Hardware

Finally...

the storage device receives the request.

SSD

↓

Read bytes

↓

Operating System

↓

libuv

↓

Node

↓

JavaScript Callback
Enter fullscreen mode Exit fullscreen mode

Only after this entire journey does your JavaScript receive the file.


Complete Flow

Let's put everything together.

Suppose we execute:

const fs = require("fs");

fs.readFile("hello.txt", (err, data) => {
    console.log(data.toString());
});
Enter fullscreen mode Exit fullscreen mode

The internal flow looks like this.

JavaScript

↓

V8 executes JavaScript

↓

Node API (fs)

↓

C++ Binding

↓

libuv

↓

Operating System

↓

SSD

↓

Operating System

↓

libuv

↓

C++ Binding

↓

JavaScript Callback

↓

console.log()
Enter fullscreen mode Exit fullscreen mode

Notice something interesting.

The request travels down through every layer.

The result travels back up through every layer.

Node acts as a bridge between JavaScript and the operating system.


An Important Observation

Many tutorials say:

"Node.js executes JavaScript."

Technically...

that's not completely accurate.

A more precise statement is:

The V8 Engine executes JavaScript. Node.js provides the runtime environment, native APIs, C++ bindings, and operating system integration that allow JavaScript to perform tasks beyond the language itself.

This distinction matters.

Understanding it changes how you see Node forever.


Final Thoughts

Today we followed a single JavaScript statement all the way from your code to the hardware.

We learned that Node.js is not simply "JavaScript outside the browser."

It is a carefully designed runtime built from multiple independent components working together:

  • V8 executes JavaScript.
  • Node APIs expose new capabilities.
  • C++ Bindings translate JavaScript into native operations.
  • libuv provides cross-platform asynchronous I/O.
  • The Operating System performs system-level work.
  • The Hardware ultimately executes the request.

Every file read...

every HTTP request...

every database connection...

every Express server...

travels through this architecture.

Understanding these layers is the difference between using Node.js...

and understanding Node.js.


Coming Next

In Part 3, we'll answer one of the most misunderstood questions in backend development:

Why is Node.js asynchronous, and what really happens inside fs.readFile() versus fs.readFileSync()?

We'll explore:

  • Blocking vs Non-Blocking I/O
  • Synchronous execution
  • Asynchronous execution
  • The Event Loop (from first principles)
  • Why Node.js doesn't stop while waiting for I/O
  • Where libuv actually fits into the story

Instead of memorizing "Node is asynchronous," we'll understand why it works that way.

Top comments (0)