Build a Server With Only node:http
Before you reach for Express or Fastify, it's worth knowing this: Node ships with everything you need to
run a real web server in its built-in node:http module. Express and Fastify are conveniences over
this — and once you've built a JSON API with only the standard library, every Node framework reads as
"node:http with the boilerplate removed." This is the roots guide: learn it and app.get(...) stops
being magic, because you'll have written the thing it wraps.
The mental model is small. http.createServer gives you a server; you hand it one request listener
— a function (req, res) called for every request. req is a readable stream of the incoming request
(method, url, headers, body); res is a writable stream you set a status + headers on and write the
response to. There's no router and no middleware — you write a router by switching on req.method and
req.url, and "middleware" is just a function you call before your handler. Hold "a server calls your
(req, res) function for each request, and you do the rest," and the whole Node web stack opens up.
📝 This is a roots guide — it assumes JavaScript/Node: functions,
async/await, callbacks, streams basics (JavaScript From Zero) and basic HTTP (HTTP, Explained). It's the JS parallel to the Go net/http roots guide and is best read before or alongside Express so you can see what it adds. Examples run withnode.
How to read this
Short and foundational — read in order. It builds a bare server, then a full JSON API (a small messages service), then maps it onto Express. Phases carry difficulty badges.
The phases
- The node:http Mental Model 🟢 —
createServer, the(req, res)listener, and how a request flows. - Handling Requests & Responses 🟡 — method/url/headers, reading the body, and writing JSON with a status.
- Routing by Hand 🟡 — switching on method + path, and why a real router exists.
- Middleware Is Just a Function 🟡 — wrapping handlers, and the chain Express formalizes.
- A JSON REST API With No Framework 🔴 — full CRUD for the messages resource, standard library only.
- Async, Streams & Structure 🔴 — promises in handlers, streaming, graceful shutdown, and layout.
- What Express Adds 🟢 — mapping Express back onto this, and when you don't need a framework.
The throughline:
http.createServercalls your(req, res)function per request; routing and middleware are code you write. That'snode:http, and it's the skeleton inside every Node framework.