Menu

Node.js Runtime: How JavaScript Runs Outside the Browser

What the Node.js runtime is, how it differs from the browser, and the core APIs — globals, modules, process, fs — that make server-side JavaScript possible.

What Node Actually Is

Node.js is a program you install on your computer that runs JavaScript files. That's the simplest description, and it's accurate. When you type node script.js, Node reads the file, hands it to Google's V8 engine (the JavaScript engine from Chrome), and executes it — with a big library of extra APIs bolted on for things V8 can't do by itself.

V8 knows how to run JavaScript. It doesn't know how to open a file, listen on a TCP socket, spawn a process, or read an environment variable. Node provides all of that, written in C++, and exposes it to your JavaScript as built-in modules.

node --version
node script.js

So Node isn't a language. It isn't a framework. It's a runtime: V8 plus a standard library plus a module system plus an event loop. That's the whole thing.

A First Script

Any .js file is a valid Node program. No boilerplate, no main function:

index.js
Output
Click Run to see the output here.

console.log works the same as in the browser. Template literals, Date, arrays, promises — all the language features you already know come from V8 and behave identically. What changes in Node is what's available around the language.

Globals That Only Exist in Node

The browser has window, document, localStorage, fetch. Node has a different set of globals, shaped around being a server-side runtime:

index.js
Output
Click Run to see the output here.
  • process is the running Node process. It carries environment variables (process.env), command-line arguments (process.argv), and methods to exit (process.exit(1)).
  • __filename and __dirname give you the absolute path of the current file and its folder. (In ES modules they don't exist — you use import.meta.url instead.)
  • global is the top-level object, the Node equivalent of window.

There's no document and no window. If you try to use them, you get ReferenceError. That's usually the first clue that a library was written for the browser and won't run in Node as-is.

Command-Line Arguments and Environment

A huge chunk of what Node is used for — CLIs, build scripts, servers — needs to read arguments and environment variables. Both live on process:

index.js
Output
Click Run to see the output here.

process.argv is an array: the first two entries are the Node binary path and the script path, so real arguments start at index 2. process.env is a plain object of environment variables — reading NODE_ENV, PORT, or API keys from it is standard practice.

Built-In Modules

Node ships with a standard library accessed through require (CommonJS) or import (ESM). The module names start with node: to make it explicit they're built in:

index.js
Output
Click Run to see the output here.

The ones you'll reach for most:

  • node:fs — read and write files. Use node:fs/promises for the async/await version.
  • node:path — join, resolve, and parse file paths in a cross-platform way.
  • node:http / node:https — build HTTP servers and make requests.
  • node:url — parse and construct URLs.
  • node:os — information about the host machine.
  • node:crypto — hashing, random bytes, encryption.

You don't install these. They come with Node. Everything else comes from npm.

The Event Loop, Briefly

Node runs your JavaScript on a single thread, but it handles many things at once. The trick is the event loop. When you call something async — a file read, an HTTP request, a timer — Node hands the actual work off to the OS (or to its thread pool) and keeps executing. When the work finishes, a callback is queued, and the loop picks it up when the current code is done.

index.js
Output
Click Run to see the output here.

The order printed is 1, 4, 2, 3. Synchronous code runs first. Then microtasks (resolved promises). Then timers. That's why a slow CPU-bound loop blocks your whole server — there's only one thread for your code. Node's concurrency is about I/O, not computation.

A Tiny HTTP Server

The payoff of all this is that a working web server fits in a few lines:

index.js
Output
Click Run to see the output here.

No framework, no dependencies. createServer takes a function that runs on every request; listen starts the event loop processing incoming connections. Real apps use Express or Fastify on top of this, but underneath it's the same built-in http module.

Node vs the Browser

It's worth being explicit about what carries over and what doesn't:

Works in bothNode onlyBrowser only
Language features (classes, promises, async/await)fs, http, process, __dirnamewindow, document, DOM
console.logCommonJS require / Node-specific ESM quirkslocalStorage, sessionStorage
fetch (Node 18+)Access to the file system and network socketsUser events, rendering
setTimeout, setIntervalChild processes, streamsHistory API, navigator

Modern Node has picked up several browser APIs — fetch, URL, AbortController, structuredClone — so the gap is narrower than it used to be. But the DOM isn't coming to Node, and the file system isn't coming to the browser.

Node vs Deno vs Bun

Node is the default, but it's no longer the only JavaScript runtime. Deno and Bun are alternatives — Deno from the original creator of Node, Bun from a newer team focused on speed. They run JavaScript (and TypeScript, natively), ship built-in tooling like test runners and bundlers, and differ from Node in how they handle modules, permissions, and package installation.

For learning JavaScript, Node is still where the documentation, tutorials, and job listings live. The concepts — event loop, modules, built-in APIs — transfer to the other runtimes almost entirely. Learn Node first; pick up the others when a project calls for them.

Running Scripts, Quickly

A few ways to actually execute code while you're working:

# Run a file
node script.js

# Run a one-liner
node -e "console.log(2 ** 10)"

# Open the REPL (interactive prompt)
node

# Watch a file and re-run on save (Node 18.11+)
node --watch script.js

The REPL is a nice scratchpad when you want to check what a method returns without creating a file. --watch is handy during development — save, and Node re-runs your script automatically.

Next: Catching Errors

Running code is one thing; handling it when something goes wrong is another. File reads fail, HTTP requests time out, JSON parses throw. The next chapter is about try/catch, error types, and the patterns for dealing with things that break — which in a Node program, eventually, everything does.

Frequently Asked Questions

What is the Node.js runtime?

Node.js is a program that runs JavaScript outside the browser. It bundles Google's V8 engine (the same one that runs JS in Chrome) with a C++ layer that provides APIs V8 doesn't have on its own — file system access, networking, processes, timers. The combination is what lets you build servers, CLIs, and build tools in JavaScript.

How is Node different from the browser?

Both run JavaScript, but the APIs around the language differ. The browser gives you window, document, and the DOM. Node gives you process, fs, http, __dirname, and CommonJS/ESM module loading. There's no DOM in Node and no file system in the browser — the language is shared, the platform isn't.

Is Node.js a framework or a runtime?

A runtime. Node itself doesn't impose any application structure — it just executes JavaScript and exposes APIs. Frameworks like Express, Next.js, or NestJS are built on top of Node. Deno and Bun are alternative JavaScript runtimes that compete with Node but play the same role.

What is the event loop in Node?

The event loop is what lets Node handle many things at once on a single thread. When you call something async — a file read, an HTTP request, a setTimeout — Node hands the work off to the system and keeps running. When the work finishes, its callback gets queued and the event loop picks it up. That's why fs.readFile doesn't block the rest of your program.

Learn to code with Coddy

GET STARTED