Backend6 min read

Express.js

Minimal Node.js web framework - build REST APIs with routing, middleware, and request/response handling in fewer than 50 lines of setup.

Express.jsNode.jsREST APIMiddlewareJavaScript

skill: Express.js category: Backend tags: [Express.js, Node.js, REST API, Middleware, JavaScript] readingTime: 6

Express is the default Node.js framework for REST APIs - minimal and composable. For APIs that need type safety and validation out of the box, consider Fastify (faster, TypeScript-native). For full-stack with TypeScript, consider tRPC or NestJS.

Workflow

  1. Set up Express with TypeScriptType-safe Express routes catch parameter mismatches and body type errors at compile time.
  2. Structure routes with Express RouterPutting all routes in index.ts becomes unmanageable. Router separates concerns and enables resource-based file organization.
  3. Validate request bodies with ZodExpress doesn't validate request data by default - parsing untrusted req.body without validation is a security risk.
  4. Add authentication middlewareMiddleware runs before route handlers - ideal for auth checks that apply to many routes.
  5. Handle errors centrallyCatching errors in every route handler creates repetition. A centralized error handler standardizes error format and logging.

Output Format

Express REST API with typed routes, Zod validation, JWT auth middleware, and central error handling.

src/
├── app.ts            # Express setup, middleware
├── server.ts         # Listen + graceful shutdown
├── routes/
│   ├── users.ts
│   └── posts.ts
├── middleware/
│   ├── authenticate.ts
│   └── errorHandler.ts
├── schemas/           # Zod schemas
└── services/          # DB + business logic

Examples

Input

Output

Edge Cases & Gotchas

  • async route handlers don't catch by default - async functions in routes that throw won't call the error middleware. Use a wrapper: const wrap = fn => (req, res, next) => fn(req, res, next).catch(next).
  • Large payload DoS - Default express.json() has no size limit. Set limit: '1mb' to prevent request body attacks.
  • Route order matters - Express matches routes in declaration order. Generic routes (/:id) must come after specific ones (/profile) or they shadow them.
  • CORS preflight on non-GET routes - Browsers send OPTIONS preflight for POST/PUT/PATCH with custom headers. Ensure cors() middleware handles OPTIONS before other middleware.

When to Break These Rules

  • Use Fastify instead of Express when throughput is the primary concern - Fastify is 2-3x faster and has schema-based validation built in.
  • Use NestJS instead of Express when the team benefits from Angular-like structure (decorators, modules, DI) for large REST or GraphQL APIs.

Reference Files

  • https://expressjs.com/en/guide/routing.html
  • https://expressjs.com/en/guide/error-handling.html

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.