interface Bucket { count: number; resetAt: number; } export class RateLimiter { private buckets = new Map(); constructor( private readonly max: number, private readonly windowMs: number, ) {} check(ip: string): boolean { const now = Date.now(); if (this.buckets.size > 10_000) this.prune(now); const existing = this.buckets.get(ip); const bucket = existing && existing.resetAt > now ? existing : { count: 0, resetAt: now + this.windowMs }; if (!existing || bucket !== existing) this.buckets.set(ip, bucket); bucket.count++; return bucket.count <= this.max; } private prune(now: number): void { for (const [ip, bucket] of this.buckets) { if (bucket.resetAt <= now) this.buckets.delete(ip); } } }