One router per feature (routes/auth.js, routes/users.js, etc.). Mount each under a path in app.js. Apply per-router middlewares. Keep public routes outside auth routers. Keep app.js thin: only global middlewares, router mounts, and the error handler.
Express Router Best Practices for Large Apps
How should I organize routes in a large Express app?
The answer
More FAQs in Express Router Best Practices for Large Apps
Mount routers under /api/v1, /api/v2, etc. Each version has its own router. Bump the version on breaking changes. Non-breaking changes (adding fields) do not need a new version.
Use router.use(middleware) at the top of the router file. Every route in the router now runs that middleware. Useful for auth and role checks across a feature.
Yes for nested resources (e.g., /users/:userId/posts). Use router.use('/:userId/posts', postsRouter). Limit nesting to one level. For deeper resources, use a separate top-level router with a filter.
Still have questions?
Browse all our FAQs or reach out to our support team
Want to upskill yourself?
Your learning library
Small steps. Big possibilities.
Find your next course. Build something great.