>_
EngineeringNotes
← Back to Node.js & Runtimes
Module 01

Node.js Fundamentals

Without Event Loop. Understand the runtime, V8, Libuv, and the core philosophy of Node.js.

01

What is Node.js?

Node.js is a runtime environment that allows JavaScript to run outside the browser.

Before Node.js

JavaScript → Browser only

With Node.js

JavaScript → Server + Backend

Use Cases

  • REST APIs
  • Backend services
  • Real-time apps (chat, notifications)
  • CLI tools

Interview Line

Node.js is a runtime environment built on the V8 engine that allows JavaScript to run outside the browser.

02

Node.js Architecture

Node.js is built on two core components:

1. V8 Engine (Execution Layer)

  • • Developed by Google
  • • Converts JavaScript → Machine Code
  • • Runs your JS code

2. Libuv (Async Layer)

  • Handles:
  • • File system
  • • Network calls
  • • Thread pool
  • • Delegates heavy work to OS

Architecture Flow

JavaScript Code → V8 (Main Thread)
Libuv handles async work
03

Single-Threaded Concept (Very Important)

Is Node.js single-threaded?

Correct Answer:

JavaScript execution → Single-threaded
Node.js internally → Multi-threaded

Clear Understanding
ComponentBehavior
JS CodeSingle thread
I/O TasksMulti-threaded (Libuv)

Key Idea

You write single-threaded code, but Node executes efficiently using background threads.

04

Blocking vs Non-Blocking

Blocking Code

sync.js
javascript
import fs from 'fs';

const data = fs.readFileSync('file.txt');
console.log("Done");
Problem:
  • • Execution stops
  • • Server cannot handle other requests

Non-Blocking Code

async.js
javascript
import fs from 'fs';

fs.readFile('file.txt', () => {
    console.log("Done");
});

console.log("Next");
Output:
Next
Done

Core Concept

Node.js uses non-blocking I/O.

05

Why Node.js is Fast

Reasons

  • Non-blocking I/O
  • Efficient async handling
  • No thread per request

CPU-Heavy Task Problem

blocking.js
javascript
while(true) {}
Issue:
  • • Blocks main thread
  • • Server becomes unresponsive

Rule

Node.js is best for I/O-heavy, not CPU-heavy tasks.

06

Core Modules

1. File System (fs)
javascript
javascript
import { promises as fs } from 'fs';

const data = await fs.readFile('data.json', 'utf-8');
2. Path (path)
javascript
javascript
import path from 'path';

const fullPath = path.join(__dirname, 'public', 'index.html');
3. Events (events)
javascript
javascript
import { EventEmitter } from 'events';

const emitter = new EventEmitter();

emitter.on('login', (user) => {
    console.log(`${user} logged in`);
});

emitter.emit('login', 'Shivam');
07

Global process Object

app.js
javascript
console.log(process.env);
process.exit();

Uses

  • Environment variables
  • Process control
08

Interview Questions (Fundamentals)

Theory Questions

What is Node.js?
Answer:Runtime environment to run JavaScript outside browser using V8.
Is Node.js single-threaded?
Answer:JS runs on one thread, but Node uses multiple threads internally for async work.
What is non-blocking I/O?
Answer:Code continues execution without waiting for tasks to finish.
Why Node.js is fast?
Answer:Non-blocking, event-driven, efficient threading.
Why avoid CPU-heavy tasks?
Answer:They block the main thread and stop request handling.
What is the difference between V8 and Libuv?
V8Libuv
Executes JS (Execution Layer)Handles async work (I/O Layer)
Machine code conversionThread pool & Event system

Coding Questions

Q1: Custom Event Logger

Create an event emitter that logs a timestamp every time a 'data' event is fired. (Demonstrates understanding of core events module).

Solution
javascript
import { EventEmitter } from 'events';

const logger = new EventEmitter();

logger.on('data', (msg) => {
  console.log(`[${new Date().toISOString()}] ${msg}`);
});

logger.emit('data', 'User connected');
// Output: [2026-04-16T12:00:00.000Z] User connected
Q2: Predict the Output (Blocking vs Non-Blocking)

What will be printed to the console and why?

Solution
javascript
import fs from 'fs';

console.log("A");

fs.readFile('large.txt', () => {
  console.log("B");
});

console.log("C");

/* 
Output:
 A
 C
 B
 
Why? fs.readFile is non-blocking. It delegates the reading to Libuv and 
immediately moves to the next line. 'B' prints later when the callback 
is pushed back to the Call Stack.
*/