Case study / 03

Rate Limit Project - Algorithm Comparison from Scratch

A production-ready rate limiting solution implementing Fixed Window Counter and Sliding Window Log algorithms from scratch with pluggable storage backends, per-client configuration, and tests that prove exactly where the fixed window fails.

Status
Selected work
System context
TypeScript, Node.js, Express.js, Redis
Source
Public repository

01 / System behavior

Interactive proof

A project-specific technical mechanism based on the recorded architecture and implementation context.

Interactive proofRate Limit Project - Algorithm Comparison from Scratch
Fixed windowBoundary burst
Sliding windowPrecise limit

Context and intent

Instead of reaching for a library, this project implements two rate limiting algorithms from zero to understand the actual mechanics - the algorithm, the storage implications, the header conventions, and the subtle failure mode that makes one algorithm strictly more correct than the other.

The Fixed Window Counter divides time into discrete intervals and maintains a simple counter per window - O(1) time and space, but susceptible to boundary bursts where a client can fire 2x the intended limit by timing requests around window boundaries. The Sliding Window Log stores an array of timestamps per client, filtering expired entries on each request - precise limiting with no boundary gaming, at the cost of O(n) memory per client.

03 / Architecture record

Architecture

A structured reading of the architecture recorded with this project.

Architecture recordRate Limit Project - Algorithm Comparison from Scratch
Per-client configuration is defined in clients
The middleware pipeline is straightforward
Both strategies accept an IRateLimitStorage in their constructor
Read the full architecture record

The middleware pipeline is straightforward: Logger → Auth → Rate Limiter → Handler. Two routes demonstrate the difference - GET /foo uses Fixed Window, GET /bar uses Sliding Window.

Both strategies accept an IRateLimitStorage in their constructor. The storage interface is deliberately minimal: get, set, increment, decrement, reset - any backend that can do these five operations can plug in.

Per-client configuration is defined in clients.ts, mapping client IDs to per-endpoint limits. The middleware extracts the route, looks up the client's config, and passes specific limits to whichever limiter is active.

How the system is shaped

Both strategies share the same IRateLimitStrategy interface, making algorithm swapping a one-word change in the route definition. Storage backends are equally pluggable via IRateLimitStorage - in-memory for development, Redis for production/distributed deployments.

A dedicated comparison test creates both limiters, runs the same sequence against both, and asserts their different behaviors at the window boundary - making the algorithmic difference viscerally visible in the test output.

05 / Selected highlights

Selected implementation notes

The decisions and workflows that carry the most explanatory weight.

  1. Two interchangeable rate limiting algorithms (Fixed Window Counter & Sliding Window Log) behind a single IRateLimitStrategy interface
  2. Pluggable storage backends via IRateLimitStorage - in-memory (Map-based) and Redis (with setWithExpiry and connection lifecycle management)
  3. Per-client, per-endpoint rate limit configuration - different clients get different limits on different routes, mirroring real API platform tiers
  4. Strategy comparison test that directly demonstrates the boundary burst vulnerability: same request sequence, different algorithm results
  5. Standard X-RateLimit-* response headers (Limit, Remaining, Window-Ms, Strategy) plus Retry-After on 429 - follows the IETF draft spec
  6. Full middleware pipeline: Logger → Auth (Bearer token) → Rate Limiter → Handler

06 / Supported metrics

Verified project record

Algorithms Implemented
2
Storage Backends
2
Boundary Burst Proof
IETF-Compliant Headers
4

Technology in context

TypeScript, Node.js, Express.js, Redis, Jest

View source repository