Sliding Window Rate Counter
Enforce a per-key request rate limit with a sliding window of timestamps, smoothing the bursts a fixed window allows.
Code
export class SlidingWindowLimiter {
constructor(limit, windowMs) {
if (!Number.isInteger(limit) || limit <= 0) throw new RangeError('limit must be positive');
if (!Number.isInteger(windowMs) || windowMs <= 0) throw new RangeError('windowMs must be positive');
this.limit = limit;
this.windowMs = windowMs;
this.hits = new Map();
}
allow(key, now = Date.now()) {
const cutoff = now - this.windowMs;
const times = (this.hits.get(key) ?? []).filter((t) => t > cutoff);
if (times.length >= this.limit) {
this.hits.set(key, times);
return { allowed: false, retryAfterMs: times[0] + this.windowMs - now };
}
times.push(now);
this.hits.set(key, times);
return { allowed: true, remaining: this.limit - times.length };
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.