Node.js cheat sheet

A scannable Node.js reference: 25 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Node.js: getting startedNode.js runs JavaScript on the server using V8, the same engine as Chrome. Its defining trait is a single-threadedlesson
Files and paths in NodeReading a multi-gigabyte file into memory with readFile will exhaust the heap. Streams process it in chunks withlesson
Building an HTTP serverA server with no framework, routing by hand, reading the body, and when to reach for Express-style librarieslesson
Modules, ESM and CommonJSNode supports two module systems side by side. CommonJS (require) is the original: synchronous, resolved at run timelesson
Events, streams and buffersMuch of Node's API is an EventEmitter: objects that announce facts and let any number of listeners react. Emitting islesson
Async patterns, timers and the event loopThe event loop is a sequence of phases. Each phase runs its callbacks, then the microtask queue drains completelylesson
Configuration, environment and CLI argumentsRead the environment once, at startup, and turn it into a validated object. Scattering process.env lookups through thelesson
Errors, logging and debuggingCustom error classes with cause chaining, exit codes that mean something, structured logs, and the built-in inspectorlesson
Testing with the built-in test runnerNode ships a test runner. No framework, no configuration file: a file named *.test.js with node:test imports islesson
Databases, HTTP clients and external servicesfetch with timeouts, retries and idempotency, connection pooling, migrations and transaction boundarieslesson
Worker threads, child processes and clusteringMoving CPU-bound work off the event loop, running other programs safely, scaling across cores, and shutting everylesson
Security, performance and deploymentValidate input at the boundary, limit and time every call, profile before optimising, and ship a small container thatlesson

Quick snippets

Node.js: getting started

What Node.js is

node --version
node app.js
node                      # REPL
npm init -y               # create package.json

Modules

// CommonJS (traditional)
const fs = require("fs");
module.exports = { helper };

// ES modules (modern; "type": "module" in package.json or .mjs)
import { readFile } from "node:fs/promises";
export function helper() {}

Configuration

const port = Number(process.env.PORT ?? 3000);

if (process.env.NODE_ENV !== "production") {
  console.warn("running in development mode");
}

process.exitCode = 1;   // prefer this over process.exit()

Full lesson: Node.js: getting started →

Files and paths in Node

Reading and writing

import { readFile, writeFile, mkdir } from "node:fs/promises";
import path from "node:path";

const file = path.join(process.cwd(), "data", "config.json");

const text = await readFile(file, "utf8");
const config = JSON.parse(text);

await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, JSON.stringify(config, null, 2), "utf8");

Paths done right

import path from "node:path";
import { fileURLToPath } from "node:url";

const here = path.dirname(fileURLToPath(import.meta.url));
const target = path.join(here, "..", "public", "index.html");

path.extname(target);        // '.html'
path.basename(target);       // 'index.html'
path.resolve("a", "b");      // absolute
path.normalize("a/../b");    // 'b'

Streams for large data

import { createReadStream, createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";
import { createGzip } from "node:zlib";

await pipeline(
  createReadStream("access.log"),
  createGzip(),
  createWriteStream("access.log.gz")
);

Full lesson: Files and paths in Node →

Building an HTTP server

Framework or no framework

// the same idea in Express
import express from "express";
const app = express();
app.use(express.json({ limit: "100kb" }));
app.get("/health", (req, res) => res.json({ ok: true }));
app.post("/echo", (req, res) => res.json(req.body));
app.listen(3000);

Full lesson: Building an HTTP server →

Modules, ESM and CommonJS

Two module systems, one runtime

// greeting.cjs — CommonJS
const os = require("node:os");

function greet(who) {
  return "hello " + who;
}

module.exports = { greet, platform: os.platform() };

Two module systems, one runtime

// greeting.js — ES module ("type": "module")
import os from "node:os";

export function greet(who) {
  return "hello " + who;
}

export const platform = os.platform();

Interop and dynamic import

// ESM can import CommonJS: the default export is module.exports
import legacy from "./greeting.cjs";
const name = legacy.greet("Ada");

// CommonJS cannot require() an ESM graph that awaits at the top level,
// so reach for the asynchronous form instead
async function load() {
  const { greet } = await import("./greeting.js");
  return greet("Ada");
}

Full lesson: Modules, ESM and CommonJS →

Events, streams and buffers

EventEmitter

import { EventEmitter } from "node:events";

const bus = new EventEmitter();

bus.on("order.paid", (order) => console.log("ship", order.id));
bus.once("ready", () => console.log("first time only"));
bus.on("error", (err) => console.error("bus failed", err));

bus.emit("order.paid", { id: 1042 });   // listeners run right here
bus.listenerCount("order.paid");        // 1
bus.removeListener("order.paid", handler);
bus.removeAllListeners();

Buffers, encoding and backpressure

const buf = Buffer.from("hello", "utf8");

buf.length;                       // 5 — bytes, not characters
buf.toString("base64");           // "aGVsbG8="
Buffer.byteLength("héllo");  // 6 — the accent is two bytes
Buffer.concat([buf, Buffer.from("!")]);   // one allocation, no string round-trip

// honour backpressure: write() returns false when the buffer is full
import { once } from "node:events";
if (!out.write(chunk)) {
  await once(out, "drain");
}

Full lesson: Events, streams and buffers →

Async patterns, timers and the event loop

What the loop actually runs

console.log("1 sync");

setTimeout(() => console.log("5 timeout"), 0);
setImmediate(() => console.log("6 immediate"));
queueMicrotask(() => console.log("3 microtask"));
process.nextTick(() => console.log("2 nextTick"));
Promise.resolve().then(() => console.log("4 promise"));

// sync, then nextTick, then promise/microtask,
// then timeout and immediate — which of the last two first is not guaranteed
// at the top level, but inside an I/O callback setImmediate always wins.

Timers and async discipline

import { setTimeout as sleep } from "node:timers/promises";

const id = setTimeout(() => console.log("late"), 5000);
clearTimeout(id);

// unref() lets the process exit even though the timer is pending
setTimeout(() => console.log("breathe"), 100).unref();

const started = performance.now();
await sleep(250);                     // awaitable, no callback pyramid
console.log(performance.now() - started);

Cancellation and failures

const controller = new AbortController();
const { signal } = controller;

await fetch(url, { signal });
await sleep(1000, { signal });

controller.abort(new Error("deadline exceeded"));  // the reason is preserved

process.on("unhandledRejection", (reason) => {
  console.error("unhandled rejection", reason);
  process.exitCode = 1;
});

Full lesson: Async patterns, timers and the event loop →

Configuration, environment and CLI arguments

process.env and env files

# the shell way
export DATABASE_URL=postgres://localhost/app
PORT=8080 NODE_ENV=production node server.js

# Node 20.6+ reads a file itself, no dotenv import needed
node --env-file=.env server.js
node --env-file-if-exists=.env.local server.js

process.env and env files

const required = ["DATABASE_URL", "JWT_SECRET"];

for (const key of required) {
  if (!process.env[key]) {
    throw new Error("missing required environment variable: " + key);
  }
}

const port = Number(process.env.PORT ?? 3000);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
  throw new Error("PORT must be a valid port number");
}

Full lesson: Configuration, environment and CLI arguments →

Errors, logging and debugging

Exit codes and structured logging

const log = (level, message, fields = {}) =>
  process.stdout.write(
    JSON.stringify({ time: new Date().toISOString(), level, message, ...fields }) + "\n"
  );

log("info", "order created", { orderId: 1042, userId: 7 });

process.on("uncaughtException", (err) => {
  log("fatal", "uncaught exception", { message: err.message, stack: err.stack });
  server.close(() => process.exit(1));
});

Debugging a running process

node --inspect-brk src/server.js    # pause on the first line, open chrome://inspect
node --inspect=0.0.0.0:9229 app.js  # only inside a trusted container
node --watch src/server.js          # restart on file change, development only
node --trace-warnings app.js
node --stack-trace-limit=50 app.js
node --cpu-prof src/worker.js       # writes a .cpuprofile you can open in DevTools

kill -USR1 <pid>                    # start the inspector on an already-running process

Full lesson: Errors, logging and debugging →

Testing with the built-in test runner

The first test

node --test                  # discover and run every matching file
node --test --watch          # rerun on change
node --test test/unit/*.test.js
node --test --test-only      # run just the tests marked with { only: true }

Watch, coverage and setup

node --test --test-concurrency=4
node --test --experimental-test-coverage --test-coverage-lines=80
node --test --test-name-pattern="checkout"
node --test --test-reporter=spec
node --test --test-reporter=junit --test-reporter-destination=report.xml
node --test --import ./test/setup.js   # global hooks, tracing, env defaults

Full lesson: Testing with the built-in test runner →

Databases, HTTP clients and external services

Outbound HTTP with fetch

const res = await fetch("https://api.example.com/orders/1042", {
  signal: AbortSignal.timeout(2000),          // Node 17.3+
  headers: { accept: "application/json" },
});

if (!res.ok) {
  const detail = (await res.text()).slice(0, 200);
  throw new Error("upstream " + res.status + ": " + detail);
}

const order = await res.json();

Full lesson: Databases, HTTP clients and external services →

Worker threads, child processes and clustering

child_process

import { spawn, execFile } from "node:child_process";
import { promisify } from "node:util";
import { pipeline } from "node:stream/promises";

// spawn streams output — the safe default for long or large jobs
const child = spawn("ffmpeg", ["-i", "in.mp4", "out.webm"], {
  stdio: ["ignore", "pipe", "pipe"],
});
await pipeline(child.stdout, process.stdout);

// execFile runs a known binary with an argument array and captures the output
const { stdout } = await promisify(execFile)("git", ["rev-parse", "HEAD"]);

Full lesson: Worker threads, child processes and clustering →

Security, performance and deployment

Limits and dependencies

// fixed-window limiter backed by Redis
async function allow(key, limit = 100, windowSeconds = 60) {
  const bucket = "rl:" + key + ":" + Math.floor(Date.now() / 1000 / windowSeconds);
  const count = await redis.incr(bucket);
  if (count === 1) await redis.expire(bucket, windowSeconds);
  return count <= limit;
}

res.setHeader("ratelimit-limit", "100");
res.setHeader("ratelimit-remaining", String(Math.max(0, limit - used)));

Profiling and deployment

node --cpu-prof --cpu-prof-dir=./prof src/server.js
node --heap-prof src/server.js
node --max-old-space-size=512 src/server.js   # cap the heap below the container limit
node --report-on-signal --report-signal=SIGUSR2 src/server.js

Full lesson: Security, performance and deployment →

FAQ

Is this Node.js cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the Node.js course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Node.js course — it carries the worked explanations, the edge cases and the exercises behind every line here.

PHP Java HTTP Go Rust Spring Boot

Last refreshed 2026-09-27.