Rate Limiting APIs: Algorithms and Headers
Rate limits protect your API from abuse, runaway scripts and accidental traffic spikes, and keep things fair between customers.
Common algorithms
- Fixed window - count requests per calendar minute. Simple, but allows bursts at window edges (100 at 12:00:59 and 100 at 12:01:00).
- Sliding window - counts over the last 60 seconds at any moment. Smoother and fairer.
- Token bucket - a bucket refills at a steady rate; each request takes a token. Allows short bursts up to the bucket size while enforcing an average rate.
Sliding window with Redis
// Allows 'limit' requests per 'windowMs' per key, using a sorted set of timestamps
async function isAllowed(redis, key, limit, windowMs) {
const now = Date.now();
const results = await redis
.multi()
.zRemRangeByScore(key, 0, now - windowMs) // drop old entries
.zAdd(key, { score: now, value: `${now}-${Math.random()}` })
.zCard(key)
.pExpire(key, windowMs)
.exec();
const count = results[2];
return { allowed: count <= limit, remaining: Math.max(0, limit - count) };
}
Using Redis means every API server shares the same counters, which in-memory limits can't do.
Tell clients what's happening
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30
Retry-After is standard. The RateLimit-* headers come from an IETF draft and are widely used; document whichever you send.
Choosing keys and limits
- Limit by API key or user ID for authenticated traffic; by IP only for anonymous endpoints.
- Use stricter limits on expensive or sensitive endpoints (login, search, exports).
- Offer higher limits on paid plans.
- Apply limits at the edge (API gateway, CDN) as well, to stop floods before they reach your servers.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.