Express Basics
10 examples to build your first Express 5 API - 7 basic and 3 intermediate.
Search across all documentation pages
10 examples to build your first Express 5 API - 7 basic and 3 intermediate.
mkdir express-api && cd express-api
npm init -y
npm pkg set type=module
npm install express@5
npm install -D typescript@5.6 tsx @types/express @types/nodeFor middleware ordering and security hardening, see Middleware Ordering and Security Middleware.
import express from "express";
const app = express();
const port = 3000;
app.get("/", (_req, res) => {
res.send("Hello from Express 5\n");
});
app.listen(port, () => {
console.log(`http://localhost:${port}`);
});app is a function that wraps Node's http.createServerres.send() sets Content-Type automatically based on the payloadimport express from "express";
const app = express();
app.use(express.json({ limit: "1mb" }));
app.post("/users", (req, res) => {
const { name, email } = req.body;
res.status(201).json({ id: 1, name, email });
});express.json() must be registered before routes that read req.bodylimit to prevent large payload attacksimport express from "express";
const app = express();
app.get("/users/:id", (req, res) => {
const { id } = req.params;
res.json({ id, name: "Ada Lovelace" });
});req.params contains named route segmentsid format in the handler or a validation middlewareimport express from "express";
const app = express();
app.get("/search", (req, res) => {
const q = req.query.q as string | undefined;
const page = Number(req.query.page ?? 1);
res.json({ q, page, results: [] });
});req.query is parsed automaticallyimport express, { Router } from "express";
const app = express();
const usersRouter = Router();
usersRouter.get("/", (_req, res) => {
res.json([{ id: 1, name: "Ada" }]);
});
usersRouter.get("/:id", (req, res) => {
res.json({ id: req.params.id });
});
app.use("/users", usersRouter);Router is a mini-app with its own middleware stackimport express from "express";
const app = express();
app.use((req, _res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.get("/health", (_req, res) => {
res.json({ status: "ok" });
});next() to pass control to the next handlerimport express from "express";
import { join } from "node:path";
const app = express();
app.use("/static", express.static(join(import.meta.dirname, "public")));express.static serves files from a directoryimport express from "express";
const app = express();
app.get("/users/:id", async (req, res) => {
const user = await findUser(req.params.id);
if (!user) {
res.status(404).json({ error: "Not found" });
return;
}
res.json(user);
});
async function findUser(id: string) {
if (id === "999") return null;
return { id, name: "Ada" };
}express-async-errors or manual try/catch wrappersimport express, { type Request, type Response, type NextFunction } from "express";
const app = express();
app.get("/fail", () => {
throw new Error("Something broke");
});
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
console.error(err);
res.status(500).json({ error: "Internal server error" });
});(err, req, res, next)import express from "express";
const app = express();
const port = Number(process.env.PORT ?? 3000);
const isDev = process.env.NODE_ENV !== "production";
if (isDev) {
app.use((req, _res, next) => {
console.log(`[dev] ${req.method} ${req.path}`);
next();
});
}
app.get("/health", (_req, res) => {
res.json({ env: process.env.NODE_ENV ?? "development" });
});
app.listen(port);PORT from the environment (Heroku, Railway, K8s all set this)NODE_ENVYes on Node 24 LTS. It is the current npm latest major. Migrate from Express 4 using the official migration guide patterns in Express 5 Migration.
Express if team familiarity and ecosystem size matter most. Fastify if throughput and JSON schema validation are priorities. See Fastify vs Express ADR.
app.listen is fine for most apps. Use createServer(app) when you need direct access to the underlying server for WebSocket upgrades or timeout tuning.
Routers per domain (/users, /orders), services for business logic, separate app.ts and server.ts. See Express Best Practices.
Yes. Set "type": "module" in package.json and use import express from "express".
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.
Reviewed by Chris St. John·Last updated Jul 16, 2026