Router-level middleware works exactly like application-level middleware, but is bound to an express.Router() instance instead of the main app object. This lesson shows how to scope middleware to a specific group of routes.
What Is Router-Level Middleware?
express.Router() creates a mini, mountable application, complete with its own middleware and routes. Calling router.use() on it registers middleware that runs only for requests handled by that specific router, not the whole app.
This is the standard way to scope logic, like auth checks or validation, to one resource's routes without leaking it into unrelated ones.
router.use() mirrors app.use(), but only applies within that router.
The router itself is mounted onto the app with app.use(mountPath, router).
Paths defined inside the router are relative to its mount path.
Multiple routers can each have their own independent middleware stack.
Router Middleware Cheatsheet
Router-scoped middleware patterns you will reuse across resource files.
Pattern
Example
Effect
Log within router
router.use(logger)
Only logs requests this router handles
Auth within router
router.use(requireAuth)
Protects every route on this router
Path-scoped in router
router.use('/:id', loadResource)
Runs before any /:id route below it
Mount router
app.use('/orders', ordersRouter)
Attaches the whole router at /orders
Per-Resource Middleware
A common pattern is to load a resource once (say, an order) in router-level middleware, attach it to req, and let every route below reuse it without repeating the lookup.
A request first passes through any matching application-level middleware, then, once it reaches a mounted router, through that router's own middleware, before finally reaching a specific route.
Forgetting to mount the router with app.use(), none of its routes or middleware ever run.
Registering router-level middleware after the routes on that same router that need it.
Duplicating the same auth check in application middleware and again in every router, when one is enough.
Assuming router-level middleware sees requests for routes mounted on a completely different router.
Key Takeaways
Router-level middleware is registered with router.use() on an express.Router() instance.
It only runs for requests dispatched to that specific router after mounting.
It is the standard way to scope logic to one resource's set of routes.
router.param() centralizes per-parameter loading logic within a router.
Pro Tip
Keep each resource's router, middleware, and routes in its own file (orders.router.js), so opening one file shows you everything that can happen to an /orders request.
You now know how to scope middleware to a router. Next, learn how to handle errors consistently with error-handling middleware.