Suggest an editImprove this articleRefine the answer for “What is Express.js and why is it used?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Express.js** is a minimal web framework for Node.js that adds routing, middleware, and HTTP utilities on top of the built-in `http` module. ```js app.use(express.json()); app.get('/users', (req, res) => res.json([{ id: 1, name: 'Alice' }])); app.listen(3000); ``` **Key:** Express turns 15+ lines of manual URL parsing and header management into 3 declarative lines. Use it for any Node.js web app unless you need 10k+ req/s (Fastify) or zero dependencies.Shown above the full answer for quick recall.Answer (EN)Image**Express.js** is a minimal web framework for Node.js that adds routing, middleware, and HTTP utilities on top of Node.js's built-in `http` module. ## Theory ### TL;DR - Express is to Node.js what a prep station is to a raw kitchen: Node gives you the stove and ingredients, Express gives you knives, cutting boards, and recipes - Main difference: 15+ lines of manual request parsing in Node.js become 3 declarative lines in Express - Express automatically handles URL routing, JSON parsing, and response headers - Decision rule: use Express for any Node.js web app unless you need zero dependencies or are running at 10k+ req/s (then Fastify) ### Quick example ```js // Pure Node.js: manual routing, manual headers, manual everything const http = require('http'); const server = http.createServer((req, res) => { if (req.url === '/users' && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify([{ id: 1, name: 'Alice' }])); } else { res.writeHead(404); res.end('Not Found'); } }); server.listen(3000); // Express: same result, 3 lines const express = require('express'); const app = express(); app.get('/users', (req, res) => res.json([{ id: 1, name: 'Alice' }])); app.listen(3000); ``` Both produce identical responses. Express removes all string matching on `req.url` and manual header management. ### What Express actually does Node.js's `http` module gives you a raw request object: a URL string, a method string, and a body as a buffer. You parse all of it yourself. Express wraps that object with a router (a radix tree for fast path lookup), attaches parsers via middleware, and gives you `res.json()`, `res.status()`, and similar helpers. You write route handlers instead of if/else chains. The middleware stack is the core idea. Every `app.use()` call adds a function to a queue. When a request comes in, Express runs each function in order, passing `req` and `res` through. If a middleware calls `next()`, the next function runs. If it calls `res.send()`, the chain stops there. ### When to use Express - REST API or web app: Express is the default pick - Prototyping: fastest path from idea to running server - Full-stack app with auth and a database: Express plus a middleware stack (cors, helmet, body-parser) - Serverless or edge functions with many routes: Express works; under 10 routes, hono.js is lighter - Microservice with a custom protocol: skip Express, use `http` directly - 10k+ requests per second in production: Fastify is about 2x faster; Express handles up to ~5k req/s comfortably ### Alternatives at a glance | Framework | Style | Best for | |---|---|---| | Express | Minimal, flexible | REST APIs, full-stack apps | | Fastify | Fast, schema-based | High-throughput APIs | | Koa | Async-first, smaller core | Greenfield projects, custom middleware | | NestJS | Opinionated, TypeScript | Enterprise apps with structure | | hono.js | Tiny, edge-ready | Serverless, Cloudflare Workers | Koa is worth knowing for interviews. It uses async/await natively where Express uses callbacks, and its core is much smaller. For new projects, Koa is a valid pick. When a large plugin ecosystem matters, Express wins. ### Common mistakes **Missing `express.json()` before routes.** This breaks around 40% of first Express apps. Without the middleware, `req.body` is `undefined` and any JSON access throws. ```js // Wrong: req.body is undefined app.post('/user', (req, res) => res.send(req.body.name)); // TypeError // Correct: parse JSON globally before any route app.use(express.json()); app.post('/user', (req, res) => res.send(req.body.name)); // "Alice" ``` **Wrong middleware order.** Middleware runs top to bottom. Register a route before `express.json()` and that route sees an unparsed body. ```js // Wrong: route runs before parser app.post('/api/user', (req, res) => res.send(req.body.name)); // undefined app.use(express.json()); // too late // Correct app.use(express.json()); // must be first app.post('/api/user', (req, res) => res.send(req.body.name)); // works ``` **Calling `res.send()` twice.** Node throws "Cannot set headers after they are sent". Fix with an early `return`. ```js // Wrong: two sends in the same handler if (err) res.status(500).send('Error'); res.json({ ok: true }); // crash // Correct if (err) return res.status(500).send('Error'); res.json({ ok: true }); ``` **No `next()` in middleware.** The request hangs. No response reaches the client, timeouts fire in production monitors. ```js // Wrong: request hangs forever app.use((req, res, next) => { console.log(req.method); // forgot next() }); // Correct app.use((req, res, next) => { console.log(req.method); next(); }); ``` ### Real-world usage - **Strapi**: headless CMS with 1M+ downloads, built on Express for REST endpoints and admin panel - **Ghost**: blogging platform, Express handles dynamic routes and themes - **PayloadCMS**: Express plus TypeScript for e-commerce backends, 10k+ developers - **Next.js API routes**: uses an Express-like router internally for `/pages/api` handlers - Most internal Node.js tools at companies start with Express and only move to Fastify when throughput becomes the actual problem I've seen teams use Express for years without hitting its performance ceiling, because the real bottleneck is usually the database query. If a query takes 50ms, Express overhead of 0.1ms does not matter. ### Follow-up questions **Q:** What is middleware in Express and how does it work? **A:** A middleware is a function with signature `(req, res, next)`. Express calls them in order for every request. You use them to parse bodies, check auth, log requests, or attach data to `req`. If a middleware skips calling `next()`, the chain stops and the client gets no response. **Q:** How does Express handle async errors? **A:** It does not automatically catch them. If you throw inside an async route handler, Express won't pick it up. Wrap every handler in try/catch and call `next(err)`, or use the `express-async-errors` package which patches the router to catch Promise rejections. **Q:** What is the difference between `app.get()` and `router.get()`? **A:** `app` is the global Express instance. `router` is a mini Express app you can mount at a path. Use `router` to group routes by prefix: `app.use('/api', router)` mounts all router routes under `/api`. This keeps large codebases modular without one giant file. **Q:** How does Express routing scale to hundreds of routes? **A:** Express uses a radix tree for route matching. Lookup is O(k) where k is path length, not O(n) routes. So 1000 routes do not slow down matching compared to 10 routes. **Q:** Express vs Koa: when would you pick Koa? **A:** Koa uses async/await natively and has a smaller core with no built-in middleware. Good pick for new projects where you want full control over the stack. Express has a larger plugin ecosystem and more community examples. Teams on existing Node.js codebases usually stay with Express because switching costs outweigh the benefits. ## Examples ### Basic REST API with JSON body parsing ```js const express = require('express'); const app = express(); app.use(express.json()); // parse JSON request bodies app.get('/users', (req, res) => { res.json([{ id: 1, name: 'Alice' }]); }); app.post('/users', (req, res) => { const { name } = req.body; // works because of express.json() res.status(201).json({ id: 2, name }); }); app.listen(3000, () => console.log('Running on 3000')); ``` `app.use(express.json())` runs before every route. A POST to `/users` with a JSON body gets `req.body` automatically populated. Without that line, `req.body` is `undefined` and the destructuring crashes. ### Webhook handler with middleware order (production pattern) This is how Stripe webhook verification looks in a real Express app: ```js const express = require('express'); const app = express(); // Raw buffer needed for signature check - must come before express.json() app.use('/webhook/stripe', express.raw({ type: 'application/json' })); app.use(express.json()); // JSON parsing for all other routes app.post('/webhook/stripe', (req, res) => { const sig = req.headers['stripe-signature']; if (!verifySignature(sig, req.body)) { return res.status(400).send('Invalid signature'); } console.log('Event:', req.body.type); // 'payment_intent.succeeded' res.json({ received: true }); }); app.listen(3000); ``` The `/webhook/stripe` route needs the raw buffer to verify the signature. Everything else gets parsed JSON. Middleware order controls which parser runs first, so the specific route middleware is registered before the global one. This is a real pattern from projects like PayloadCMS. For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.