DEV Community

Cover image for Day 26 of #100DaysOfCode — Modular Routing
M Saad Ahmad
M Saad Ahmad

Posted on

Day 26 of #100DaysOfCode — Modular Routing

When your backend server starts small, having all your routes inside a single app.js file feels simple and convenient.
But as your application grows, more pages, more API endpoints, more middleware. It becomes harder to maintain. This is exactly where modular routing in Express.js shines.

Day 26 was about how modular routing works, why it matters, and how it keeps your project clean and scalable.


🚩 The Problem: One Massive app.js

If you don’t break routes into separate files, your main server file might look like this:

// app.js
app.get('/users', ...)
app.post('/users', ...)
app.get('/products', ...)
app.post('/products', ...)
// and eventually it becomes unmanageable...
Enter fullscreen mode Exit fullscreen mode

This gets messy fast—especially once middleware, controllers, authentication, or validation get added.


✅ The Solution: Modular Routing

Modular routing lets you split related routes into separate files using the Express Router object.
It keeps your project organized by grouping endpoints by feature (users, products, posts, auth, etc.).

🗂 Example: Modular Routing Done Right

/routes/users.js

const router = require('express').Router();

// GET /users
router.get('/', (req, res) => {
  res.send("Get all users");
});

// POST /users
router.post('/', (req, res) => {
  res.send("Create a user");
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

/routes/products.js

const router = require('express').Router();

// GET /products
router.get('/', (req, res) => {
  res.send("Get all products");
});

// POST /products
router.post('/', (req, res) => {
  res.send("Create a product");
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Clean app.js

const express = require('express');
const app = express();

const usersRouter = require('./routes/users');
const productsRouter = require('./routes/products');

app.use('/users', usersRouter);
app.use('/products', productsRouter);

app.listen(3000, () => console.log("Server running on port 3000"));
Enter fullscreen mode Exit fullscreen mode

Your app.js finally stays clean and easy to read.


🔍 How Modular Routing Works in Express.js

Below are the core concepts that make modular routing so powerful.


1. The Express Router Object

express.Router() creates isolated mini-apps that you attach to your main app.
Each router supports its own routes, middleware, and logic.

Think of routers as small “sub-apps” that plug into your main Express instance.


2. Route Prefixing

When you use:

app.use('/users', usersRouter);
Enter fullscreen mode Exit fullscreen mode

Every route inside the users router automatically inherits /users as a prefix.

So inside users.js, this:

router.get('/');
Enter fullscreen mode Exit fullscreen mode

Becomes:

GET /users
Enter fullscreen mode Exit fullscreen mode

This is incredibly helpful for structuring RESTful APIs.


3. Splitting by Feature (Best Practice)

A common, scalable structure:

/routes
   users.js
   products.js
   auth.js
   orders.js
/controllers
   usersController.js
   productsController.js
app.js
Enter fullscreen mode Exit fullscreen mode

Each file focuses on one feature or resource, which improves:

  • readability
  • maintainability
  • teamwork
  • testing

4. Route-Level Middleware

Routers can have their own middleware—like authentication, validation, or logging.

router.use((req, res, next) => {
  console.log("Users route hit");
  next();
});
Enter fullscreen mode Exit fullscreen mode

Or middleware for a specific route:

router.get('/', authMiddleware, getUsers);
Enter fullscreen mode Exit fullscreen mode

This keeps the logic separated and prevents your main app from being bloated.


5. Controllers (Basics)

For even cleaner projects, routes and logic are split:

Route file

router.get('/', usersController.getAllUsers);
Enter fullscreen mode Exit fullscreen mode

Controller file

exports.getAllUsers = (req, res) => {
  res.send("Get all users from controller");
};
Enter fullscreen mode Exit fullscreen mode

This is the foundation of scalable Express apps and prepares you for MVC-style architecture.


🎯 Final Thoughts

Modular routing is one of the first major steps toward building maintainable backend applications. Breaking routes into separate files, organizing them by feature, and using controllers makes your code cleaner and easier to grow.

It is essential for backend applications to maintain structure, even as they scale to dozens or hundreds of routes.

If you're learning Express.js, mastering modular routing early will save you a lot of headaches later!

Happy coding!

Top comments (0)