Script Valley
System Design: APIs, Caching & Scalability
Rate Limiting and ThrottlingLesson 4.2

Fixed window vs sliding window rate limiting algorithms

fixed window algorithm, sliding window log algorithm, sliding window counter, boundary spike problem, memory trade-offs, algorithm selection

Fixed window vs sliding window rate limiting algorithms

Fixed vs sliding window rate limiting

Fixed Window

Divide time into fixed intervals such as each minute. Count requests per interval and reset at the boundary. Simple and memory-efficient:

const key = `ratelimit:${userId}:${Math.floor(Date.now() / 60000)}`;
const count = await redis.incr(key);
await redis.expire(key, 60);
if (count > 100) return res.status(429).json({ error: 'Rate limit exceeded' });

Problem: a client sends 100 requests at 00:59 and 100 more at 01:01 — 200 requests in 2 seconds across two windows, both under the limit. This boundary spike can overwhelm your backend.

Sliding Window Log

Store a timestamp for each request in a sorted set. Remove timestamps older than the window, then check count. Accurate but memory-intensive:

const now = Date.now();
const windowStart = now - 60000;
await redis.zremrangebyscore(key, 0, windowStart);
const count = await redis.zcard(key);
if (count >= 100) return res.status(429).end();
await redis.zadd(key, now, now);
await redis.expire(key, 60);

Sliding Window Counter

Hybrid approach: use two fixed-window counters (current and previous minute) weighted by how far into the current window you are. Approximates sliding window at fixed-window memory cost. Used by Cloudflare at scale. For most applications, fixed window is sufficient — only move to sliding window if boundary spikes are measurable in your production metrics.

Up next

Token bucket and leaky bucket rate limiting explained

Sign in to track progress