1. Window edge
The cutoff marks the trailing edge of the window: any hit at or before it has expired.
const cutoff = now - this.windowMs;Typorithm · medium
Step 1 of 8 · intro card
Applied Patterns
Allow at most N requests per rolling time window per user. Keep a queue of recent hit timestamps; on each call drop any older than now minus the window, then admit only if the surviving count is under the limit.
An API must allow each user at most N requests per W milliseconds — but the window rolls continuously, not in fixed buckets, so a burst at a bucket boundary cannot sneak through.
The sliding-window pattern keeps a queue of recent hit timestamps. On every call you first slide the window forward by discarding timestamps older than now minus the window length.
Whatever survives is exactly the set of requests still inside the live window. If that count is below the limit you push the new timestamp and admit; otherwise you reject.
Store hit timestamps in arrival order.
Each call prunes timestamps that fell out the back.
Admit only while the live count is under the limit.
class RateLimiter {
constructor(limit, windowMs) {
this.limit = limit;
this.windowMs = windowMs;
this.hits = [];
}
allow(now) {
const cutoff = now - this.windowMs;
while (this.hits.length && this.hits[0] <= cutoff) {
this.hits.shift();
}
if (this.hits.length < this.limit) {
this.hits.push(now);
return true;
}
return false;
}
}Connect each part of the code to the concept before you type.
The cutoff marks the trailing edge of the window: any hit at or before it has expired.
const cutoff = now - this.windowMs;Each call slides the window forward by removing timestamps that fell out the back.
while (this.hits.length && this.hits[0] <= cutoff) {shift removes the oldest timestamp from the front, since hits are stored in arrival order.
this.hits.shift();After pruning, the remaining count is exactly the requests inside the live window.
if (this.hits.length < this.limit) {Recording the new timestamp counts this request toward the next window's budget.
this.hits.push(now);Read the concept map and follow the code breakdown.
Type the implementation, repair mistakes and work through every recall exercise.
Use the final check without hints; revisit weak concepts in short practice sessions.