Sitemap

Express.js Secrets That Senior Developers Don’t Share

4 min readFeb 21, 2025

--

Press enter or click to view image in full size
Express.js Secrets That Senior Developers Don’t Share
Express.js Secrets That Senior Developers Don’t Share

Express.js is often the go-to framework for building web applications in Node.js. It’s lightweight, unopinionated, and incredibly flexible, making it a favorite among both beginners and experienced developers. However, there’s a gap between writing basic Express apps and building scalable, maintainable, and high-performance applications.

Senior developers, especially those who’ve spent years in production environments, have hard-earned secrets that make their Express applications faster, safer, and easier to maintain. These insights rarely make it into tutorials or official documentation.

1. Using Middleware Wisely: The Hidden Performance Cost

Middleware is at the heart of Express. However, misusing middleware can slow down your app and cause bottlenecks. Here’s what most people get wrong:

Common Mistake: Using Too Many Global Middleware

Many developers add middleware at the top level, affecting every single request, even if it’s not needed:

app.use((req, res, next) => {
console.log('Request received');
next();
});

app.use(someHeavyMiddleware);

app.get('/simple-route', (req, res) => {
res.send('Hello, world!');
});

Here, even a simple route like /simple-route has to go through someHeavyMiddleware, slowing things down.

The Senior Dev Fix: Apply Middleware Selectively

Instead, attach middleware only where necessary:

app.get('/simple-route', (req, res) => {
res.send('Hello, world!');
});

app.use('/heavy-api', someHeavyMiddleware);
app.get('/heavy-api/data', (req, res) => {
res.send('This route actually needs heavy middleware');
});

Pro Tip: Use router.use() Instead of app.use()

Instead of attaching middleware globally, bind it only to relevant routers:

const userRouter = express.Router();
userRouter.use(authMiddleware);
userRouter.get('/profile', (req, res) => {
res.send('User profile');
});

app.use('/user', userRouter);

Now, authMiddleware only affects /user routes.

2. Secret Sauce: Async Error Handling Like a Pro

Handling errors in async functions can get messy and repetitive. Most developers write error-prone code like this:

app.get('/data', async (req, res) => {
try {
let data = await fetchData();
res.send(data);
} catch (err) {
res.status(500).send('Something went wrong');
}
});

What’s wrong? Every route needs the same try/catch pattern, leading to bloated code.

The Senior Dev Fix: Use a Universal Async Error Handler

Wrap your async routes with a helper function:

const asyncHandler = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};

app.get('/data', asyncHandler(async (req, res) => {
let data = await fetchData();
res.send(data);
}));

Now, errors are automatically passed to the Express error handler, keeping your code clean and DRY.

3. Mastering Express Router: The Scalability Trick

If your server.js file has 100+ routes, you’re doing it wrong. A senior developer knows that breaking routes into modular files is crucial.

The Senior Dev Fix: Organize Your Routes Properly

  1. Create a /routes directory
  2. Move each feature into its own file

For example, instead of dumping everything into server.js, create a clean structure:

/routes
├── users.js
├── products.js
├── orders.js

Then in users.js:

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

router.get('/profile', (req, res) => {
res.send('User profile page');
});

module.exports = router;

And in server.js:

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

app.use('/users', require('./routes/users'));
app.use('/products', require('./routes/products'));

app.listen(3000, () => console.log('Server running on port 3000'));

Now, your routes are modular, scalable, and easy to maintain.

4. Using Environment Variables the Right Way

Many junior developers hardcode secrets in their code:

const dbPassword = 'supersecret123';

Big mistake! Never expose secrets in your source code.

The Senior Dev Fix: Use .env Properly

  • Install dotenv:
npm install dotenv
  • Create a .env file:
DB_PASSWORD=supersecret123
  • Use it in your app:
require('dotenv').config();
const dbPassword = process.env.DB_PASSWORD;

Now, your credentials are safe and easy to change.

5. The res.locals Trick: Avoiding Unnecessary Database Calls

Many developers fetch user data in every request, slowing down performance:

app.use(async (req, res, next) => {
const user = await fetchUser(req.userId);
req.user = user;
next();
});

The Senior Dev Fix: Store Data in res.locals

Use res.locals to store request-specific data without bloating req:

app.use(async (req, res, next) => {
res.locals.user = await fetchUser(req.userId);
next();
});

app.get('/dashboard', (req, res) => {
res.send(`Welcome, ${res.locals.user.name}`);
});

This keeps req lightweight and your middleware efficient.

6. The Lesser-Known next('route') Trick

Sometimes, you want to skip the current middleware and jump to the next route handler. Most developers don’t realize next('route') exists!

The Senior Dev Fix: Conditional Route Skipping

app.get('/admin', checkAuth, (req, res, next) => {
if (!req.user.isAdmin) return next('route'); // Skip this handler
res.send('Welcome, Admin!');
});

app.get('/admin', (req, res) => {
res.send('You are not an admin');
});

Now, non-admin users skip the first handler and get a friendly message instead.

Final Thoughts: Write Express Like a Senior Developer

Express is simple to learn, but hard to master. By applying these hidden techniques, you’ll write applications that are:

→ Faster — By reducing unnecessary middleware and optimizing route handling
Cleaner — Using modular routing and async error handling
More secure — By using .env and avoiding secret leaks
More maintainable – By keeping request-specific data lightweight

The difference between a junior and a senior developer is not knowledge of the framework, but how they use it wisely.

You may also like:

1) 5 Common Mistakes in Backend Optimization

2) 7 Tips for Boosting Your API Performance

3) How to Identify Bottlenecks in Your Backend

4) 8 Tools for Developing Scalable Backend Solutions

5) 5 Key Components of a Scalable Backend System

6) 6 Common Mistakes in Backend Architecture Design

7) 7 Essential Tips for Scalable Backend Architecture

8) Token-Based Authentication: Choosing Between JWT and Paseto for Modern Applications

9) API Rate Limiting and Abuse Prevention Strategies in Node.js for High-Traffic APIs

10) Can You Answer This Senior-Level JavaScript Promise Interview Question?

11) 5 Reasons JWT May Not Be the Best Choice

12) 7 Productivity Hacks I Stole From a Principal Software Engineer

13) 7 Common Mistakes in package.json Configuration

Read more blogs from Here

Share your experiences in the comments, and let’s discuss how to tackle them!

Follow me on Linkedin

--

--

Responses (11)