Back to results for “Async Patterns”
Node.js › Express & Middleware

How do you write custom Express middleware that needs to perform asynchronous work, like checking a value against a database, before calling next()?

Advanced

Answer

An async middleware function performs its await-based work and then calls next() to continue the chain, or next(err) to forward an error -- because Express (pre-v5) doesn't automatically catch a rejected promise from an async middleware, any error thrown inside it needs to be explicitly caught and passed to next(err), typically using the same asyncHandler wrapper pattern used for async route handlers.
const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);

const checkRateLimit = asyncHandler(async (req, res, next) => {
  const requestCount = await redis.incr(`rate:${req.ip}`);
  if (requestCount > 100) return res.status(429).json({ error: 'Too many requests' });
  next();
});

app.use(checkRateLimit);
Real-world example A rate-limiting middleware that queries Redis asynchronously before deciding whether to allow a request through is wrapped in an asyncHandler utility, ensuring that if the Redis call itself fails, the error is properly forwarded to Express's error-handling middleware rather than crashing the process.

Common follow-ups: What happens specifically if this async middleware throws without being wrapped in asyncHandler, in an Express 4 application?;How does this pattern differ once Express 5's native async error handling makes the wrapper largely unnecessary?