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-limit2
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
- Use tighter limits for login and password reset endpoints.
- Key login limits by IP and email when possible.
- 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.