A service enforces 'max 60 requests per minute per client' using a fixed window counter that resets every minute on the wall clock (e.g. at :00 of each minute). Why can a client legitimately send close to 120 requests in a short burst spanning a minute boundary, and how does a sliding window approach address this?
answer
- boundary burst ~2x
- hard clock-aligned reset
- sliding window log = exact, O(n)
- sliding window counter = weighted estimate, O(1)
- Cloudflare's published approach
basics
~20 sFixed windows reset abruptly at a clock boundary, so a client can max out the limit right before the reset and again right after — nearly double the intended limit in a short burst. Sliding window looks at a rolling time range instead of a fixed clock tick, so it never lets that double-up happen.
solid answer
~50 sA fixed window counter resets to zero at each clean minute boundary (12:00:00, 12:01:00, ...). Nothing stops a client from sending 60 requests at 12:00:59 (filling the window right at the end) and another 60 at 12:01:00 the instant it resets — 120 requests land within roughly 1-2 seconds of wall-clock time, even though the stated limit is 60/minute. This is the classic boundary burst problem: the algorithm enforces the limit per fixed bucket, not per rolling minute. Sliding window log fixes this by keeping a timestamped log of every request in the last 60 seconds and counting how many fall within that rolling range on each new request — exact but memory-heavy. Sliding window counter approximates it cheaply by weighting the previous window's count proportionally to how much of it still overlaps the current rolling window (Cloudflare's published approach), trading a small approximation error for O(1) space per client instead of O(n).
go deeper
Should be able to describe, in plain terms, that resetting a counter at a fixed clock tick can let two bursts land close together.
Should explain the mechanism precisely — why up to ~2x the limit can occur at the boundary — and name sliding window log as a fix.
Expected to compare sliding window log vs sliding window counter's cost/accuracy trade-off and justify which to use under high request volume.
Expected to reason about which endpoints actually need boundary-burst protection (e.g., auth endpoints under brute-force risk) versus where fixed window's simplicity is an acceptable trade against the cost of exact/approximate sliding window at scale.
## The simplest implementation A fixed window counter is the simplest rate-limiting implementation: 1. pick a window size (e.g., 60 seconds), 2. align windows to clock boundaries (12:00:00-12:00:59, 12:01:00-12:01:59, ...), 3. keep one counter per client per window. Every request increments the counter for whichever window it falls into; if the counter exceeds the configured limit, the request is rejected. The counter is trivially reset by simply starting a new key (or letting the old one expire) at each boundary, which is exactly why it's popular: it requires only a single integer per client and an expiry, cheap to store and cheap to check. ## The boundary burst The mechanism's flaw is precisely its cleanliness: because the reset is a hard clock-aligned event, the algorithm has **no memory** of how requests were distributed within the previous window once it rolls over. A client that understands this can: - send its full quota of 60 requests in the last second of one window (12:00:59), - then, the instant the clock ticks to 12:01:00, send another full quota of 60 requests. From the algorithm's point of view both are perfectly compliant — each window individually saw exactly 60 requests — but from the backend's point of view, roughly 120 requests arrived within about one second of real time, double the intended sustained rate and potentially enough to overload the very capacity the limiter exists to protect. This is called the **boundary burst** (or edge-burst) problem, and it exists for any fixed-window scheme regardless of window length. ## Sliding window log — exact, and priced accordingly Sliding window approaches fix this by evaluating a rolling range ending at "now," rather than a fixed clock-aligned bucket. The precise version, **sliding window log**, stores a timestamp for every accepted request per client (e.g., in a Redis sorted set keyed by client, scored by timestamp). On each new request, the limiter: 1. evicts entries older than (now - window size), 2. counts what remains, 3. if that count is below the limit, the request is accepted and its timestamp added. This is exact — it can never be fooled by a boundary burst because it's always looking at a true rolling 60-second window — but its cost scales with the number of requests per window per client, since every request's timestamp must be stored and later pruned, expensive at high request rates or high client cardinality. ## Sliding window counter — the practical compromise Sliding window counter is the practical compromise most production systems actually use — this is the algorithm Cloudflare has published details on for their edge rate limiter. It keeps just two fixed-window counters per client: - the count for the current window, - the count for the immediately previous window. To estimate the request rate over the trailing 60 seconds at any instant, it computes a weighted sum: `current_window_count + previous_window_count × (fraction of the previous window's span still inside the trailing 60-second range)`. Thirty seconds into the current minute, roughly half of the previous window's requests are treated as still "in range," so the estimate is `current_count + previous_count × 0.5`. This is an approximation — it assumes requests were spread evenly across the previous window, which isn't always true — but it closes almost all of the boundary-burst gap while keeping storage at O(1) per client instead of O(n), which is why it's the default choice at high scale. ## Precision versus cost The trade-off is precision versus cost: | Approach | What you pay for it | |---|---| | fixed window | cheapest and simplest but allows up to ~2x burst at boundaries | | sliding window log | exact but its storage and pruning cost grows with traffic volume, which can itself become a capacity problem under high request rates or a DDoS-style flood, ironically undermining the very protection the limiter provides | | sliding window counter | sits in between, cheap like fixed window but accurate enough in practice that the residual approximation error rarely matters for capacity protection, as opposed to, say, billing, where exactness might matter more | ## What to watch for in production The production failure mode to watch for is choosing fixed window for an endpoint where the boundary burst genuinely matters — a login endpoint being brute-forced, for instance, where an attacker who understands the reset boundary can precisely time two full-quota bursts back to back — and discovering the gap only after an incident rather than during design.
- Does the sliding window log approach ever produce a false rejection or false acceptance?No — it is mathematically exact because it counts real timestamps within the true rolling window, with no approximation. Its downside is purely operational cost (storage and pruning), not correctness.
- What real-world attack specifically benefits from the fixed-window boundary burst?A brute-force login or credential-stuffing attacker who knows or can infer the window boundary can time two full-quota bursts back to back across the reset instant, getting roughly double the intended attempt budget in a very short real-time span — much more dangerous on a low-limit, high-value endpoint like login than on a generic read API.
- How does sliding window counter's weighting formula behave for a request landing right at the very start of the current window?At that instant almost the entire trailing 60-second range still overlaps the previous window, so the weight applied to the previous window's count is close to 1.0, making the estimate nearly equal to the previous window's full count plus a tiny contribution from the new window — exactly the behavior needed to catch a boundary burst that fixed window would miss.
Fixed window is like a water park that lets in 60 people right at 12:00 and again right at 12:01 with no memory in between — two crowds can pile up back to back at the gate. Sliding window is like continuously checking 'how many people entered in the last 60 seconds, starting from right now' no matter what the clock says.
saying these in an interview costs you the question
- Claims fixed window is always sufficient and boundary bursts don't matter in practice
- Confuses sliding window log's O(n) storage cost with sliding window counter's O(1) cost
- Thinks sliding window counter is exact rather than an approximation
- Can't explain why the reset in fixed window causes the problem