Express Router
Part of the Backend Developer Roadmap
In short
One index.js with forty routes gets messy fast. express.Router lets you group related routes into their own files and plug each group in with one line.
Express's `Router` class lets you group related routes into their own modular, mountable mini-applications — essential for keeping a growing API organized.

Think of it like this
The college food court
The food court has separate stalls: dosa, chaat, juice. Each stall runs its own menu and staff, but they all share one entrance. Each Router is a stall with its own routes, and app.use mounts it at the entrance.
Watch it happen
An app built from routers
1/5index.js creates the app and mounts two routers.
The big ideas
What you need to know
A mini app
A Router has its own routes and middleware. It behaves like a small Express app you can mount.
Paths are relative
Inside a router mounted at /api/users, router.get("/:id") answers /api/users/:id.
Group middleware
router.use(requireAuth) protects every route in that router, and only those.
One file per resource
routes/users.js, routes/orders.js. New teammates find code by guessing the file name.
See it in code
Walk through the code
1// routes/orders.js2import { Router } from "express";3import { requireAuth } from "../middleware/auth.js";4 5export const ordersRouter = Router();6ordersRouter.use(requireAuth);7 8ordersRouter.get("/", (req, res) => res.json({ userId: req.user.id, orders: [] }));9ordersRouter.post("/", (req, res) => res.status(201).json(req.body));10 11// index.js12import { ordersRouter } from "./routes/orders.js";13import { usersRouter } from "./routes/users.js";14app.use("/api/orders", ordersRouter);15app.use("/api/users", usersRouter);1/4Create a router in its own file and export it.
To read a parent's route param inside a router, create it with Router({ mergeParams: true }).
Save yourself the pain
Common mistakes
Oops
Writing router.get("/api/orders/:id") inside a router mounted at /api/orders.
Do this instead
Inside the router, write just "/:id". The mount path is added for you.
Oops
Putting auth with app.use before all routers, so even public routes need login.
Do this instead
Attach auth to the routers or routes that need it, and leave health checks and login public.
Your mission
Split a big app
Quick check
usersRouter has router.get("/:id/orders"), mounted with app.use("/api/users", usersRouter). Which URL matches?
Go deeper
- 1Split your routes into separate router files by resource (users, posts, orders).
- 2Mount each router under its own base path, e.g. `/api/users`.
- 3Apply router-level middleware (e.g. auth) that only affects routes in that router.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.