2 min read·Run it here

Design a Rate Limiter

A per-user quota guard using a map of keys to recent request timestamps, with retryAfter and reset as operational escape hatches.

Pattern
Map key -> sliding window timestamps
Time
O(k) per check
Space
O(keys * limit)

A rate limiter is a policy wrapped around a data structure. For this drill, the policy is simple: each key gets limit requests within the last windowMs.

The recipe

Say before you type: "Prune old timestamps. If the list is under limit, push now. Otherwise deny."

Use a Map<string, number[]>.

const cutoff = nowMs - windowMs;
const fresh = hits.filter((time) => time > cutoff);

The window is half open: > and not >=, so a hit that is exactly windowMs old has already fallen out. Decide this on the first line and say it out loud, because it is not a cosmetic choice — >= keeps one stale timestamp and shifts every retryAfter answer by a millisecond.

Then allow() is just:

  1. Prune the key.
  2. If fresh.length >= limit, return false.
  3. Push nowMs, store the list, return true.

retryAfter

retryAfter() should not mutate quota. It prunes stale timestamps, then returns:

oldestHit + windowMs - nowMs

If the key is not limited, return 0.

reset

reset(key) deletes one key. reset() clears the whole map. This is the kind of operational method interviewers like because it shows you are thinking past the pure algorithm.