Beginner

Node.js: The Big Picture

An overview of Node.js — its architecture, ecosystem, LTS model and real-world use cases.

An overview of Node.js, its architecture, ecosystem, and real-world use cases.


Table of Contents

  1. What Is Node.js?
  2. How Node.js Is Used
  3. Exploring Node.js in Practice
  4. Long-Term Support (LTS)
  5. Reference Tables
  6. Architecture Diagrams

1. What Is Node.js?

Definition and Positioning

Node.js is a standalone JavaScript runtime — an execution environment for JavaScript independent of the browser, installed directly on an operating system.

“Node.js is a standalone JavaScript runtime environment.”

Without Node.js, a .js file is just a text file. It can’t do anything on its own. Node.js provides the complete environment for JavaScript to interact with the OS, network, file system, etc.

Who uses Node.js?

CompanyUsage
NetflixStreaming, user interface
LinkedInBackend API
PayPalWeb servers
UberReal-time services
SlackDesktop application (Electron)
TrelloWeb application
eBayAPIs and microservices
NASAReal-time data management
MicrosoftVS Code (Electron/Node application)

Node.js is used to build:

  • Web applications and REST APIs
  • Streaming applications
  • Decentralized blockchain applications
  • Real-time chat and collaboration tools
  • Multiplayer games
  • Microservices
  • Serverless functions
  • CLI (command line interfaces)
  • Desktop applications (via Electron)
  • IoT (Internet of Things) controllers

Node.js Architecture

Before Node.js, JavaScript was designed to run inside the browser. The browser is a complex application that includes:

  • An HTML/CSS rendering engine
  • A network manager
  • A graphical interface
  • A JavaScript engine (e.g., V8 in Chrome)

The browser’s JavaScript engine bridges JS code and OS resources (system clock, network, files, etc.). But JavaScript itself cannot directly access the OS — that would be a major security risk.

Node.js replaces the browser as the intermediary platform between JavaScript and the OS:

JavaScript Code
      │
      ▼
┌─────────────┐
│   Node.js   │  ← replaces the browser
│  ─────────  │
│     V8      │  ← JavaScript engine (Google, open-source)
│   libuv     │  ← task controller, event loop, async I/O
│  Bindings   │  ← interface with OS (C/C++)
└─────────────┘
      │
      ▼
Operating System (OS)

V8 Engine

V8 is Google’s open-source JavaScript engine, written in C++. It is used in Chrome and in Node.js.

  • It is a JIT compiler (Just-In-Time): it compiles JavaScript into machine code at runtime
  • It is extremely performant
  • It handles garbage collection (memory)
  • It executes JavaScript synchronously on a single thread
// V8 executes this JavaScript code
const message = "Hello from V8!";
console.log(message); // → "Hello from V8!"

libuv and the Event Loop

libuv is a C library that provides Node.js with:

  • The event loop
  • Asynchronous I/O management (files, network, DNS, etc.)
  • A thread pool for blocking operations
  • Timers (setTimeout, setInterval)
  • Signals and child processes

How Does the Event Loop Work?

The event loop is the heart of Node.js. It’s what allows Node.js to be non-blocking despite a single JavaScript execution thread.

// Event loop demonstration
console.log("1 - Synchronous (start)");

setTimeout(() => {
  console.log("3 - Timer callback (macrotask)");
}, 0);

Promise.resolve().then(() => {
  console.log("2 - Promise callback (microtask)");
});

console.log("4 - Synchronous (end)");

// Output:
// 1 - Synchronous (start)
// 4 - Synchronous (end)
// 2 - Promise callback (microtask)
// 3 - Timer callback (macrotask)

Why this order? Synchronous code runs first. Microtasks (Promises, queueMicrotask) take priority over macrotasks (setTimeout, setInterval, I/O callbacks).

Event Loop Phases

   ┌───────────────────────────┐
   │        timers             │  ← setTimeout, setInterval callbacks
   └──────────┬────────────────┘
              │
   ┌──────────▼────────────────┐
   │   pending callbacks       │  ← I/O errors from previous cycle
   └──────────┬────────────────┘
              │
   ┌──────────▼────────────────┐
   │      idle, prepare        │  ← internal Node.js use
   └──────────┬────────────────┘
              │
   ┌──────────▼────────────────┐
   │          poll             │  ← retrieve new I/O events
   └──────────┬────────────────┘
              │
   ┌──────────▼────────────────┐
   │          check            │  ← setImmediate callbacks
   └──────────┬────────────────┘
              │
   ┌──────────▼────────────────┐
   │    close callbacks        │  ← e.g.: socket.on('close', ...)
   └───────────────────────────┘

Bindings API

Bindings are the C/C++ interfaces that allow JavaScript to communicate with the operating system. They enable:

  • System clock access (Date.now())
  • File read/write
  • TCP/UDP network connections
  • External process execution
  • Native module integration (.node files in C++)

2. How Node.js Is Used

The Module System

Node.js organizes code into modules. A module is a JavaScript file that encapsulates reusable code. Two module systems exist:


CommonJS vs ESM

CharacteristicCommonJS (CJS)ES Modules (ESM)
Import syntaxrequire()import
Export syntaxmodule.exportsexport / export default
LoadingSynchronousAsynchronous
File extension.js (default).mjs or "type": "module"
Specification2009 (Node.js)ES2015 (official ECMAScript)
Browser supportNo (native)Yes
Top-level awaitNoYes
Tree-shakingDifficultPossible
// ─── CommonJS (CJS) ───────────────────────────────────────────
// math.js
function add(a, b) { return a + b; }
module.exports = { add };

// index.js
const { add } = require('./math');
console.log(add(2, 3)); // 5

// ─── ES Modules (ESM) ─────────────────────────────────────────
// math.mjs (or package.json with "type": "module")
export function add(a, b) { return a + b; }

// index.mjs
import { add } from './math.mjs';
console.log(add(2, 3)); // 5

Best practice: For new projects, prefer ESM ("type": "module" in package.json). It’s the modern standard aligned with browsers.


Essential Built-in Modules

Node.js ships with a rich standard library:

// HTTP Server
import { createServer } from 'http';

const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello, World!\n');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});
// Streams - processing large data in chunks
import { createReadStream, createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';
import { createGzip } from 'zlib';

// Compress a file without loading everything into memory
await pipeline(
  createReadStream('input.txt'),
  createGzip(),
  createWriteStream('output.txt.gz')
);
console.log('Compression complete!');
// Events - EventEmitter
import { EventEmitter } from 'events';

const emitter = new EventEmitter();

// Listen for an event
emitter.on('data', (payload) => {
  console.log('Data received:', payload);
});

// Emit an event
emitter.emit('data', { user: 'Alice', action: 'login' });
// → Data received: { user: 'Alice', action: 'login' }
// File System (fs) - asynchronous reading
import { readFile, writeFile } from 'fs/promises';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const filePath = join(__dirname, 'data.json');

const content = await readFile(filePath, 'utf-8');
const data = JSON.parse(content);
data.updatedAt = new Date().toISOString();

await writeFile(filePath, JSON.stringify(data, null, 2));
console.log('File updated');
// Path - cross-platform path manipulation
import path from 'path';

const fullPath = path.join('/users', 'alice', 'documents', 'file.txt');
console.log(fullPath);                // /users/alice/documents/file.txt
console.log(path.extname(fullPath));  // .txt
console.log(path.basename(fullPath)); // file.txt
console.log(path.dirname(fullPath));  // /users/alice/documents
// Built-in test runner (stable since Node.js 20)
import { test, describe } from 'node:test';
import assert from 'node:assert/strict';

describe('My add() function', () => {
  test('returns the sum of two numbers', () => {
    assert.equal(2 + 3, 5);
  });

  test('handles negative numbers', () => {
    assert.equal(-1 + 1, 0);
  });
});

npm and Package Management

npm (Node Package Manager) is Node.js’s official package manager. It installs automatically with Node.js.

It provides:

  1. A CLI tool for managing project dependencies
  2. A public registry with over 2 million open-source packages

Initialize a Project

# Create a new project (interactive)
npm init

# Create a new project (automatic answers)
npm init -y

# Set ESM module type
npm pkg set type=module

Manage Dependencies

# Install a package (production dependency)
npm install express

# Install a package (development dependency)
npm install --save-dev jest

# Install all dependencies of an existing project
npm install

# Update packages
npm update

# Uninstall a package
npm uninstall express

# List installed packages
npm list

Example package.json

{
  "name": "my-node-app",
  "version": "1.0.0",
  "description": "A Node.js application",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "node --watch index.js",
    "test": "node --test"
  },
  "dependencies": {
    "express": "^5.1.0"
  },
  "devDependencies": {
    "eslint": "^9.0.0"
  }
}

The caret ^ before the version means: accept this major version (5) and all future minor/patch updates (5.x.x), but not the next major version (6.x.x).

Alternative Package Managers

ToolCharacteristics
npmOfficial, bundled with Node.js
YarnFaster, deterministic lockfile, workspaces
pnpmVery disk space-efficient, symlinks
BunUltra-fast runtime + package manager (Node alternative)

The Node.js Ecosystem

The Node.js ecosystem goes far beyond the runtime itself. The community has produced thousands of frameworks, libraries, and tools.

Web Frameworks

FrameworkDescriptionType
ExpressMinimal and flexible framework, most popularServer-side
FastifyExpress alternative, very performantServer-side
KoaCreated by the Express team, more modernServer-side
HapiRobust framework for enterprise APIsServer-side
NestJSTypeScript framework with architecture focusServer-side
Next.jsReact + SSR + API routesFull-stack
Nuxt.jsVue.js + SSR + API routesFull-stack
RemixFull-stack React with focus on web standardsFull-stack

Databases

CategoryPopular Tools
ORM/ODMPrisma, TypeORM, Mongoose, Sequelize, Drizzle
SQLpg (PostgreSQL), mysql2, better-sqlite3
NoSQLMongoDB (via Mongoose), Redis (ioredis)
MigrationsKnex.js, db-migrate

Testing

ToolType
JestFull-featured test framework (unit, integration)
VitestJest alternative, Vite-compatible
MochaFlexible test framework
ChaiAssertions library
SupertestHTTP API testing
PlaywrightBrowser end-to-end testing
node:testBuilt-in test runner (stable since v20)

Build Tools and Bundlers

ToolUsage
webpackEstablished bundler, highly configurable
ViteModern bundler, ultra-fast
esbuildUltra-fast bundler (Go)
RollupLibrary bundler
ParcelZero-config bundler
tscTypeScript compiler

Code Quality Tools

ToolUsage
ESLintJavaScript/TypeScript linter
PrettierCode formatting
HuskyGit hooks
lint-stagedLinting before commit

3. Exploring Node.js in Practice

First Node.js Project

# 1. Check installed versions
node -v    # e.g.: v22.11.0
npm -v     # e.g.: 10.9.0

# 2. Initialize the project
npm init -y

# 3. Configure ESM
npm pkg set type=module

# 4. Create the main file
touch index.js
// index.js - Hello World
console.log("Hello, World!");
# 5. Run with Node
node index.js
# → Hello, World!

Complete Example: HTTP Server with Routing

// server.js
import { createServer } from 'http';

const PORT = process.env.PORT || 3000;

const routes = {
  'GET /': (res) => {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Welcome to my Node.js API!' }));
  },
  'GET /health': (res) => {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok', uptime: process.uptime() }));
  }
};

const server = createServer((req, res) => {
  const key = `${req.method} ${req.url}`;
  const handler = routes[key];

  if (handler) {
    handler(res);
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Route not found' }));
  }
});

server.listen(PORT, () => {
  console.log(`Server started at http://localhost:${PORT}`);
});

Real Questions About Node.js

Q: Your team needs a backend for a chat app handling many simultaneous lightweight connections. Is Node.js a good choice?

Yes. Node.js handles concurrent lightweight connections very well thanks to its asynchronous, single-threaded, event-driven model. It doesn’t block the main thread waiting for network or database responses. This is exactly the use case for which Node.js excels.

Q: You’re building an ML pipeline training models and performing large numerical computations. Is Node.js the best choice?

Generally, no. Heavy computations would block the main thread. Python is a better primary choice (NumPy, TensorFlow, PyTorch). However, Node.js can be useful for serving these models via an API or coordinating lightweight tasks.

Q: “Single-threaded means Node.js can’t do parallel work.” Is this accurate?

Not entirely. There’s only one process stack — two JavaScript instructions don’t execute at exactly the same time, that’s the event loop. But Node.js can still do real parallel work via:

  • child_process (child processes)
  • worker_threads (worker threads)
  • I/O operations handled in parallel by the OS via libuv

Q: A simple static site needs to serve files. Should you build a Node.js server?

No, use something else. A CDN or static host (Netlify, Vercel, S3, etc.) is simpler, cheaper, and scales automatically. Building your own Node.js server would be over-engineering for this case.

Q: Which Node.js version to choose for production?

Always an LTS (Long-Term Support) version with an even number (e.g., 20, 22, 24). Odd versions (21, 23, 25) are “Current” experimental versions preparing the next LTS.


4. Long-Term Support (LTS)

Node.js follows a well-defined release cycle with semantic versioning (SemVer): MAJOR.MINOR.PATCH.

Version Lifecycle

Version published
      │
      ▼
  Current (6 months)
  ← active development, new features ─►
      │
      ▼  (for even versions only)
  Active LTS (18 months)
  ← bug fixes, security ─►
      │
      ▼
  Maintenance LTS (12 months)
  ← critical fixes and security only ─►
      │
      ▼
  End of Life (EOL)
  ← no more support ─►

Version Table (example)

VersionStatusNote
v25.xCurrentExperimental, odd number
v24.xActive LTSRecommended for production
v22.xActive LTSPrevious LTS
v20.xMaintenance LTSNearing end of support
v18.xEOLDo not use

Golden rule: In production, use an active LTS version (even number). Avoid EOL versions that no longer receive security patches.

Node.js is open-source, community-managed via GitHub, and financially supported by the OpenJS Foundation.


5. Reference Tables

Node.js Built-in Modules

ModuleDescriptionTypical Usage
http / httpsHTTP/HTTPS server and clientCreate web servers, make requests
fs / fs/promisesFile system operationsRead/write files, manage directories
pathPath manipulation (cross-platform)Join, resolve, extract file paths
eventsEventEmitter patternPub/sub, custom events
streamStreaming APIProcess large data in chunks
bufferBinary data manipulationEncode/decode data
urlURL parsingParse and build URLs
cryptoCryptographic functionsHashing, encryption, tokens
osOS informationCPU count, memory, platform
processCurrent process controlEnvironment variables, exit, signals
child_processRun external processesShell scripts, other programs
worker_threadsReal multithreadingCPU-intensive parallel tasks
net / dgramLow-level TCP/UDPSockets, custom protocols
dnsDomain resolutionResolve hostnames
zlibCompression (gzip, deflate)Compress/decompress data
assertTest assertionsUnit tests
node:testBuilt-in test runnerUnit and integration tests
clusterMulti-process clusteringScale across CPU cores
readlineCLI inputInteractive command-line tools
querystringURL parameter parsingParse query strings

Comparison with Other Runtimes

AspectNode.jsDenoBun
CreatorRyan Dahl (2009)Ryan Dahl (2020)Jarred Sumner (2022)
EngineV8V8JavaScriptCore
SecurityOptionalPermissions by defaultPermissions by default
TypeScriptVia tsc/transpilerNativeNative
Module systemCJS + ESMESM (CJS via compat.)CJS + ESM
BundlerExternalBuilt-inBuilt-in
npm compatibleYesPartialYes
MaturityVery highGrowingRecent
Use casesAllModern projectsSpeed-critical

6. Architecture Diagrams

Node.js vs Browser Architecture

graph LR
    subgraph "Before Node.js: Browser"
        JS1[JavaScript] --> BROWSER[Browser Engine]
        BROWSER --> RENDER[Rendering Engine]
        BROWSER --> V8B[V8 JavaScript Engine]
        BROWSER --> NET1[Network Module]
        BROWSER --> DOM[DOM API]
        BROWSER --> OS1[Operating System]
    end

    subgraph "With Node.js: Server"
        JS2[JavaScript] --> NODE[Node.js Runtime]
        NODE --> V8N[V8 Engine]
        NODE --> LIBUV[libuv\nEvent Loop]
        NODE --> BINDN[C++ Bindings]
        NODE --> OS2[Operating System]
    end

    style BROWSER fill:#dbeafe
    style NODE fill:#dcfce7

npm Ecosystem

flowchart TD
    DEV[Developer] -->|npm install| NPM_CLI[npm CLI]
    NPM_CLI -->|downloads| REGISTRY["npm Registry\n(registry.npmjs.org)\n2M+ packages"]
    NPM_CLI -->|creates| NM[node_modules/]
    NPM_CLI -->|updates| PKG[package.json\npackage-lock.json]

    subgraph "Alternative CLIs"
        YARN[Yarn]
        PNPM[pnpm]
        BUN[Bun]
    end

    YARN -->|accesses| REGISTRY
    PNPM -->|accesses| REGISTRY
    BUN -->|accesses| REGISTRY

    subgraph "Package Types"
        FRAME[Frameworks\nExpress, Fastify, NestJS]
        TEST[Testing\nJest, Vitest, Mocha]
        BUILD[Build Tools\nVite, esbuild, webpack]
        UTIL[Utilities\nlodash, dayjs, zod]
    end

    REGISTRY --- FRAME
    REGISTRY --- TEST
    REGISTRY --- BUILD
    REGISTRY --- UTIL

Search Terms

node.js · apis · microservices · backend · full-stack · web · architecture · event · loop · built-in · ecosystem · npm · package · tools · version

Interested in this course?

Contact us to book it or get a custom training plan for your team.