Introduction to Node.js

Difficulty: Beginner

Node.js is a JavaScript runtime built on Chrome's V8 engine that allows you to run JavaScript outside the browser. Created by Ryan Dahl in 2009, Node.js was born out of frustration with the way web servers like Apache handled concurrent connections. Apache created a new thread for every incoming connection, which consumed significant memory and made it difficult to scale to thousands of simultaneous users. Dahl's insight was that most of the time a server spends handling a request is spent waiting for I/O operations like reading from a database or file system, and the CPU is idle during that wait.

Node.js solves this with an event-driven, non-blocking I/O model. Instead of creating a new thread for each request and blocking while waiting for I/O, Node.js uses a single thread with an event loop. When an I/O operation is initiated, Node.js registers a callback and moves on to handle the next request. When the I/O operation completes, the callback is placed in the event queue and eventually executed. This architecture makes Node.js extremely efficient for I/O-heavy workloads like web servers, APIs, real-time applications, and microservices.

The V8 engine, developed by Google for Chrome, is the heart of Node.js. V8 compiles JavaScript directly to native machine code using just-in-time (JIT) compilation rather than interpreting it line by line. This gives Node.js performance that rivals traditionally compiled languages for many workloads. V8 also handles memory management and garbage collection, so developers do not need to manually allocate or free memory.

Node.js has become one of the most popular platforms for backend development. Companies like Netflix, LinkedIn, PayPal, Uber, and NASA use Node.js in production. It excels at building RESTful APIs, real-time chat applications, streaming services, command-line tools, and serverless functions. The npm ecosystem (Node Package Manager) is the largest software registry in the world with over two million packages, giving developers access to a vast library of reusable code.

It is important to understand what Node.js is NOT ideal for. CPU-intensive tasks like video encoding, complex mathematical computations, or machine learning training can block the single thread and starve other requests. For such workloads, you would use worker threads, child processes, or offload the work to a specialized service. Node.js shines when the bottleneck is I/O, not computation.

Code examples

Your First Node.js Script

// Save this as hello.js and run: node hello.js
console.log("Hello from Node.js!");
console.log("Node version:", process.version);
console.log("Platform:", process.platform);
console.log("Architecture:", process.arch);

This script runs entirely in the terminal, not in a browser. The process object is a Node.js global that provides information about the current running process, including the Node version, operating system platform, and CPU architecture.

Non-blocking I/O in Action

const fs = require('fs');

console.log("1. Starting to read file...");

// Asynchronous (non-blocking) file read
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.log("3. File not found, but that's okay for this demo");
    return;
  }
  console.log("3. File contents:", data);
});

console.log("2. This runs BEFORE the file is read!");

Notice that line 2 prints before line 3 even though the readFile call appears first in the code. This is non-blocking I/O in action. Node.js initiates the file read operation and immediately moves to the next line. When the file operation completes (or fails), the callback function is called.

Simple HTTP Server

const http = require('http');

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

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

This creates a basic HTTP server in just a few lines. The createServer callback runs for every incoming request. Node.js can handle thousands of concurrent connections with this single-threaded model because it never blocks waiting for I/O.

Key points

Concepts covered

Node.js History, V8 Engine, Non-blocking I/O, Single-Threaded, Use Cases