Express Middleware
Middleware is a function that runs between the incoming request and your final response, with the signature (req, res, next) , letting you log, parse, authenticate, or transform every request in a pipeline.
Learn Express Middleware in our free Node.js course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Node.js course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll write your own middleware, understand why order matters, share data down the chain with req , use built-in parsers like express.json() , and add a catch-all error handler.
What You'll Learn in This Lesson
1️⃣ What Middleware Is
A middleware function takes three arguments: req (the request), res (the response), and next (a function that hands control to whatever comes next). Register it with app.use() and it runs for every request. The golden rule: always either call next() or send a response.
The middleware logged the request, then called next() to let the route handler send the actual reply. Drop the next() and the browser would spin forever — the request would never reach the handler.
2️⃣ Order Matters: a Pipeline
Middleware runs in registration order, like a pipeline. Each function can attach data to req so later functions — including your route handler — can read it. This is how things like the logged-in user or a request timer get shared down the chain.
The logger ran first, then auth, then the handler — exactly the order they were registered. Because each stored data on req , the final handler could read both req.startTime and req.user .
3️⃣ Built-in and Error-Handling Middleware
Express bundles useful middleware. express.json() parses a JSON request body onto req.body . And a special error-handling middleware — recognized by its four arguments (err, req, res, next) — catches anything that throws, so you can return a clean error instead of crashing.
Your turn. Fill in the two ___ blanks to complete a logger and a timestamp middleware, then run it.
Mini-Challenge: An API Key Gate
Write a middleware that only lets the request through when ?key=secret is present, and rejects everything else with a 401. Register it before your routes.
Common Errors (and the fix)
- The request hangs forever — A middleware neither called next() nor sent a response. Make sure every path does one or the other.
- req.body is undefined — You forgot app.use(express.json()) before the route, so the JSON body was never parsed.
- Error handler never runs — Error-handling middleware must have all four arguments (err, req, res, next) and be registered after your routes.
- "Cannot set headers after they are sent" — You sent a response and then called next() or sent again. End the cycle once; don't continue after responding.
- Middleware runs in the wrong order — Express respects registration order. Put parsers and auth above the routes that depend on them.
Pro Tips
- 💡 Scope middleware to a path: app.use("/admin", checkAdmin) runs only for URLs starting with /admin .
- 💡 Pass errors forward: in async middleware, use next(err) to route a failure to your error handler.
- 💡 One error handler at the end: keep a single four-argument handler last so it catches everything.
📋 Quick Reference — Express Middleware
Goal
Syntax
Global middleware
app.use((req, res, next) => {})
Pass control on
next()
Parse JSON body
app.use(express.json())
Path-scoped
app.use("/api", mw)
Send an error onward
next(err)
Error handler
(err, req, res, next) => {}
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ Middleware is a function with the signature (req, res, next)
- ✅ Always call next() or send a response — never both, never neither
- ✅ Middleware runs in registration order , forming a pipeline
- ✅ Attach data to req to share it down the chain
- ✅ express.json() parses JSON bodies onto req.body
- ✅ Error handlers take four arguments and go last
- ✅ Next lesson: REST APIs with Express — design clean CRUD endpoints
Practice quiz
What is the standard signature of an Express middleware function?
- (req, res, next)
- (request)
- (next, req)
- (err, data)
Answer: (req, res, next). Middleware receives the request, the response, and next().
What must you call to pass control to the next handler in the chain?
- continue()
- next()
- pass()
- done()
Answer: next(). Calling next() hands control to the following middleware or route.
What happens if a middleware forgets to call next() (and never responds)?
- Express auto-calls next
- It skips to the route
- It logs a warning only
- The request hangs forever
Answer: The request hangs forever. Without next() or a response, the request never completes and hangs.
Which method registers middleware that runs for EVERY request?
- app.get()
- app.route()
- app.use()
- app.all()
Answer: app.use(). app.use() registers middleware that runs on every incoming request.
In what order does middleware run?
- In the order it is registered
- Alphabetically
- Randomly
- Reverse of registration
Answer: In the order it is registered. Middleware executes as a pipeline, in registration order.
Which built-in middleware parses an incoming JSON request body?
- express.text()
- express.json()
- express.raw()
- express.body()
Answer: express.json(). express.json() parses JSON bodies and puts the result on req.body.
Without express.json(), what is req.body for a JSON POST?
- An empty array
- The raw string
- undefined
- An error object
Answer: undefined. Without a body parser, req.body is undefined.
How does Express recognize ERROR-handling middleware?
- By a special name
- By a decorator
- By a config flag
- By its four arguments (err, req, res, next)
Answer: By its four arguments (err, req, res, next). The four-argument signature (err, req, res, next) marks it as error middleware.
How can one middleware share data with later handlers?
- By attaching it to the req object
- Using a global variable only
- It cannot share data
- By returning it
Answer: By attaching it to the req object. Attaching properties to req (e.g. req.user) passes data down the chain.
Which status code does the example error handler send with res.status(...)?
- 200
- 500
- 404
- 201
Answer: 500. The error handler responds with res.status(500) for a server error.
Continue this course
- Previous: Express Intro & Routing
- Next: REST APIs with Express