Skip to main content

Command Palette

Search for a command to run...

What is Node.js? JavaScript on the Server Explained

Updated
11 min readView as Markdown
What is Node.js? JavaScript on the Server Explained

So you've been writing JavaScript for a while now. You're comfortable with the browser. You know how to make buttons do things. You've argued with this keyword. You've cried over async code. You're basically a JavaScript veteran at this point.

And then someone on LinkedIn casually goes, "Oh yeah, I built the backend in Node.js."

You nod. You smile. You go home and type into Google: "what is Node.js."

No judgment. That was me too. Let's fix that today.

First, A Quick Reality Check: JavaScript Was Never Supposed to Leave the Browser

Here's a fact that sounds dramatic but is completely true: JavaScript was built to live inside a browser and nowhere else.

When Brendan Eich created JavaScript back in 1995, the whole job description was: make webpages interactive. That's it. Validate a form. Show a dropdown. Change a colour on hover. Nothing more, nothing less.

The browser was JavaScript's entire universe. It had access to the DOM (the webpage structure), it had window, it had document, it had alert() which everyone overused and later regretted. But it had no concept of your file system, no concept of your computer's network ports, and absolutely no idea how to talk to a database.

If you wrote JavaScript and tried to, say, read a file from your computer? The browser would laugh at you. For security reasons, your browser-based JS is sandboxed. It cannot touch your file system. It cannot spin up a server. It cannot listen to incoming HTTP requests.

So for backend work, everyone used other languages. PHP was writing server logic. Java was powering enterprise applications. Python was doing its thing. Ruby on Rails was making developers feel cool.

JavaScript was just sitting there in the browser, minding its business.

That changed in 2009.

Enter Node.js: JavaScript, But Make It Backend

In 2009, Ryan Dahl looked at JavaScript and thought: "What if I took the JavaScript engine out of the browser and ran it directly on a computer?"

And that is exactly what Node.js is.

Node.js is a runtime environment that lets you run JavaScript outside the browser, directly on your machine or a server.

It is not a programming language. JavaScript is the language. Node.js is the environment that runs that language outside its original home. It's like JavaScript is chai. The browser is the kullad (the clay cup) it was originally served in. Node.js is the mug that lets you drink the same chai, just... somewhere else.

Same chai. Different container. Different context.

This distinction matters a lot. When people say "I write backend in Node.js," they mean they write JavaScript and run it using Node.js on a server. The language is still JavaScript. The runtime is Node.js.

How Does Node.js Actually Run JavaScript?

This is where the V8 engine comes in. But don't worry, we're keeping this high-level. No PhD required.

Every browser has a JavaScript engine, which is basically the thing that reads your JavaScript code and turns it into something your computer's processor can actually understand and execute. Chrome uses an engine called V8, built by Google.

V8 is fast. Like, genuinely fast. Google built it to make Chrome snappy and it turned out to be extremely good at its job.

Ryan Dahl took V8, pulled it out of Chrome, and embedded it into Node.js. So when you run a JavaScript file using Node.js, V8 is the thing doing the heavy lifting. It compiles your JavaScript code into machine code and runs it.

The difference is the context around V8. Inside Chrome, V8 runs alongside browser APIs like document, window, and fetch. Inside Node.js, V8 runs alongside a completely different set of APIs: ones that let you interact with the file system, create HTTP servers, work with network connections, and talk to databases.

So document.getElementById does not exist in Node.js. It has no idea what a DOM is. But fs.readFile() does exist. Because in Node.js, reading files is the whole point.

A tiny example to feel the difference:

In the browser:

// Works fine in browser
document.getElementById("myButton").addEventListener("click", () => {
  console.log("Button clicked!");
});

In Node.js:

// No DOM. No button. Just a file.
const fs = require("fs");

fs.readFile("menu.txt", "utf8", (err, data) => {
  if (err) {
    console.log("Menu not found. Zomato it is.");
    return;
  }
  console.log("Today's menu:", data);
});

Same JavaScript syntax, completely different capabilities. The language is the same. The environment is different.

The Runtime vs The Language

People mix this up all the time so let me be very clear.

JavaScript is the programming language. It has syntax rules, data types, functions, loops, all of that. The language spec is maintained by a body called ECMA International. When a new feature gets added to JavaScript (like optional chaining ?. or nullish coalescing ??), it gets added to the language spec.

A runtime is what actually executes that language. It provides the engine plus a set of built-in tools (APIs) that your code can use.

The browser is a runtime. Node.js is also a runtime. Both use V8 under the hood. But they expose different APIs.

It is like how the same recipe (JavaScript) can be cooked in a home kitchen (browser) or in a restaurant kitchen (Node.js). The recipe is the same. But the home kitchen has a microwave and a basic stove. The restaurant kitchen has a tandoor, industrial burners, and a freezer big enough to store a whole wedding buffet.

Different tools. Same recipe.

The Event-Driven Architecture Thing

Here is where Node.js was actually clever compared to the older backend approaches.

Traditional backend servers like those written in PHP or Java would handle each incoming request by spinning up a new thread. A thread is like assigning a new waiter to every single customer who walks into your restaurant. One customer arrives, one waiter gets assigned, that waiter stands next to the customer until the entire order is complete, then goes back to the pool.

This works fine when you have ten customers. When you have ten thousand customers all hitting your server at once? You run out of waiters fast. Threads are expensive. They consume memory. Spawning thousands of them puts serious pressure on your system.

Node.js took a different approach: the event-driven, non-blocking I/O model.

Instead of assigning a dedicated thread per request, Node.js runs on a single main thread and uses an event loop to handle multiple things concurrently.

Here is the idea in plain language: when Node.js gets a request that involves waiting (like reading from a database or fetching data from an external API), instead of sitting there twiddling its thumbs, it says "okay, go do that thing, and call me when you're done" and moves on to handle the next request.

When the database comes back with the data, it triggers a callback (or resolves a Promise), and Node.js handles it.

One waiter. Takes all the orders. Calls out to the kitchen. While the kitchen is cooking, takes more orders. When food is ready, serves it.

That one waiter is the event loop.

Here is a code snippet that shows this mindset:

const https = require("https");

console.log("Placing order on Swiggy...");

https.get("https://api.example.com/restaurants", (response) => {
  console.log("Swiggy responded! Status:", response.statusCode);
});

console.log("Meanwhile, I am already watching the next episode of Panchayat.");

Output:

Placing order on Swiggy...
Meanwhile, I am already watching the next episode of Panchayat.
Swiggy responded! Status: 200

Notice that? Node.js did not wait for Swiggy to respond before moving to the next line. It moved on, and handled the response when it came back. That is non-blocking I/O in action.

This makes Node.js very efficient for applications that are I/O heavy: things that spend a lot of time waiting on databases, APIs, or file reads, rather than doing intense number crunching.

Node.js vs PHP and Java

Let's be fair to everyone here.

PHP was the king of server-side web development for a long time. WordPress runs on it. A massive portion of the internet still runs on it. PHP is synchronous by default: it processes one thing at a time per request. For simple websites with low traffic, this is perfectly fine. For real-time applications handling thousands of simultaneous connections, it gets tricky.

Java is powerful, mature, and used heavily in enterprise systems. It handles concurrency through multi-threading. It is robust and scales well, but it has a reputation for being verbose. You write a lot of code to do relatively simple things. The ecosystem is heavyweight. Startup times can be slow. It is not what you'd reach for if you wanted to spin up a quick API in an afternoon.

Node.js brought something different to the table:

  • It uses the same language on both frontend and backend (JavaScript). One language, full stack.

  • It is non-blocking by design, which makes it very efficient for real-time and API-heavy applications.

  • npm (Node Package Manager) gave developers access to a massive ecosystem of packages. You don't reinvent the wheel. You npm install it.

  • It is lightweight and quick to get running. You can have a basic HTTP server running in about ten lines.

Here's a complete basic HTTP server in Node.js:

const http = require("http");

const server = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("Welcome to Ami's Coffee House. Today's special: JavaScript with extra callbacks.");
});

server.listen(3000, () => {
  console.log("Server is running on port 3000. Don't touch it. It's working.");
});

Ten lines. A working server. Compare this to the amount of boilerplate you'd write in Java to achieve the same thing and you'll understand why developers adopted Node.js so quickly.

That said, Node.js is not the best tool for everything. CPU-intensive tasks like heavy image processing, machine learning, or complex mathematical computations are not Node's strength. Because it is single-threaded at its core, a task that hogs the CPU will block everything else. For those cases, Python, Java, or Go are better fits.

Use the right tool for the right job. Node.js is excellent at what it is excellent at.

Where You Will Actually See Node.js Being Used

If you are wondering whether Node.js is actually used in the real world or just in bootcamp exercises, here is your answer:

REST APIs and Backend Services -- Most of the APIs you call in your frontend projects can be (and often are) built with Node.js. Express.js, a minimal framework built on top of Node.js, is one of the most widely used backend frameworks in web development.

Real-time Applications -- Chat applications, live notifications, collaborative tools. Things where many users are connected simultaneously and data needs to flow in real time. Node.js handles this well because of its event-driven model.

Streaming Applications -- Node.js handles streaming data very efficiently, which makes it a good fit for platforms that deal with video or audio streaming.

Command-line Tools -- A lot of developer tools you already use, like the Vue CLI, Create React App, ESLint, Prettier, are built with Node.js. When you run npm run dev, you are running Node.js.

BFF (Backend For Frontend) layers -- In larger applications, Node.js is often used as a middle layer between the frontend and multiple microservices.

Companies like LinkedIn, Netflix, Uber, PayPal, and NASA (yes, NASA) have used Node.js in production systems. LinkedIn famously moved parts of their backend from Ruby to Node.js and saw significant performance improvements.

Let's do a quick recap

  • JavaScript was originally built only for browsers. It had no way to interact with servers, file systems, or databases.

  • Node.js is a runtime that takes the V8 JavaScript engine (the same one in Chrome) and runs it outside the browser, directly on your machine or server.

  • V8 compiles JavaScript into machine code and executes it fast. Node.js wraps V8 with a set of server-side APIs.

  • Node.js uses an event-driven, non-blocking I/O model. It handles many requests efficiently using a single thread and an event loop, rather than creating a new thread per request like traditional servers.

  • Compared to PHP and Java, Node.js is lighter to start, uses one language across the stack, and is particularly well-suited for real-time and API-heavy applications.

  • You will find Node.js powering REST APIs, real-time apps, streaming services, and developer tools.