Skip to content
Security20-35 min

Express Rate Limiting Implementation

This guide adds global and route-specific limits, explains key generation, covers reverse proxy configuration, and shows how to test rate-limit behavior.

Node.jsExpressSecurity

Prerequisites

  • An Express API.
  • A list of sensitive endpoints such as login, signup, password reset, and contact forms.
  • Knowledge of whether the app runs behind a proxy or load balancer.
1

Install express-rate-limit

Implementation snippet
npm install express-rate-limit
2

Configure proxy trust

If your app runs behind Vercel, Render, Railway, Nginx, Cloudflare, or another proxy, configure Express so client IP detection works correctly.

Implementation snippet
app.set("trust proxy", 1);
3

Add a global API limit

Implementation snippet
import rateLimit from "express-rate-limit";

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  limit: 300,
  standardHeaders: true,
  legacyHeaders: false,
  message: { message: "Too many requests. Please try again soon." },
});

app.use("/api", apiLimiter);
4

Add stricter auth limits

  1. Use tighter limits for login and password reset endpoints.
  2. Key login limits by IP and email when possible.
  3. Return the same login error wording to avoid account enumeration.
Implementation snippet
const authLimiter = rateLimit({
  windowMs: 10 * 60 * 1000,
  limit: 5,
  standardHeaders: true,
  legacyHeaders: false,
});

app.post("/auth/login", authLimiter, loginHandler);
app.post("/auth/forgot-password", authLimiter, forgotPasswordHandler);
5

Use custom keys for user-specific routes

Implementation snippet
const userLimiter = rateLimit({
  windowMs: 60 * 1000,
  limit: 60,
  keyGenerator: (req) => req.user?.id || req.ip,
});
6

Verification checklist

Checklist
  • Six rapid login failures trigger a 429 response when the limit is 5.
  • Normal browsing does not hit the global limit.
  • The response includes standard RateLimit headers.
  • Production logs include enough context to spot abusive clients.

Need implementation help?

Want this built correctly in your codebase?

Send us your stack, repo context, and the feature you need. We will help you implement it cleanly and hand over the working code.

Free scoping callFixed timelineFull source ownership
Get implementation help