Conditional Middleware

Run It Only Sometimes

Conditional Middleware

Apply middleware only when a condition holds — by path, method, or env.

3 min read Level 2/5 #express#middleware#conditional
What you'll learn
  • Skip middleware conditionally
  • Apply only in specific environments
  • Use mounting paths effectively

Sometimes middleware should fire only under some conditions — specific paths, environments, or methods.

By Mount Path

The simplest filter — Express’s built-in:

app.use("/admin", requireAdmin);              // only on /admin/*
app.use("/api",   express.json());            // only on /api/*
app.use("/api/v2/uploads", express.raw());    // very specific

By Predicate — Skip Inside

function devOnly(mw) {
  return (req, res, next) => {
    if (process.env.NODE_ENV !== "development") return next();
    return mw(req, res, next);
  };
}

app.use(devOnly(morgan("dev")));

Same idea — wrap and decide.

By Method

function onlyMutating(mw) {
  return (req, res, next) => {
    if (["GET", "HEAD", "OPTIONS"].includes(req.method)) return next();
    return mw(req, res, next);
  };
}

app.use(onlyMutating(csrfProtection));

CSRF protection only matters for state-changing methods. Skip GET/HEAD/OPTIONS.

A Reusable Helper

function when(predicate, mw) {
  return (req, res, next) => {
    if (predicate(req)) return mw(req, res, next);
    return next();
  };
}

app.use(when(
  (req) => req.path.startsWith("/api"),
  authenticate
));

Disable in Tests

if (process.env.NODE_ENV !== "test") {
  app.use(rateLimit({ /* ... */ }));
}

Stops the rate-limit middleware from polluting test runs.

Avoid Heavy Conditionals

Conditionals inside middleware are a hint that you might want to split the route or mount under a different path. The clearest Express code has flat, declarative middleware — each one with one job.

Per-Route Middleware →