Rate-limit the API
Cap /api/ at 100 requests per 15 min and login at 5 failures.
shieldfy/API-Security-Checklistgithub.com
Security Checklist
From security-best-practices: express-rate-limit, a MUST.
Hammer /api/
Hold to flood past 100, then fast-forward the clock.
Press and hold, or hold Space.
No limiterBad
- Served
- 0
- Rejected
- 0
- Ceiling
- none
app.use('/api/', router)limiter: 100 / 15 minGood
- Served
- 0
- Rejected
- 0
- Resets in
- 15:00
standardHeaders: true, legacyHeaders: falseimport rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests from this IP, please try again later.',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
Guess the password
Guess, or run the attack. The real one is letmein42.
Global limit onlyBad
Account safe
Failed attempts: 0 of 100 allowed
9,600 guesses/dayauthLimiter 5 / 15 minGood
Account safe
Counted attempts 0/5
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true,
});
app.use('/api/auth/login', authLimiter);
What the numbers buy
Drag the sliders or set the list size.
guesses/day = max × (1440 / windowMin) // 5 × (1440 / 15) = 480
Why it matters, pros and cons
Why it matters
Without a ceiling, one client can exhaust the server and guess at network speed.
Pros
- One middleware line per route.
Retry-Aftertells clients when to retry.- Successful sign-ins never count toward lockout.
Cons
- Memory store is per process; share it via Redis.
- Per-IP keys punish NATs and miss botnets.
- Behind a proxy, set
trust proxyor everyone shares one IP.