You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A production-style API Gateway built with Node.js, Express, and Redis that demonstrates real-world rate limiting patterns, reverse proxying, and observability.
What This Project Is
A two-service system where all client traffic flows through a gateway before reaching a backend API. The gateway enforces rate limiting using Redis — blocked requests never reach the backend.
# Hit /api/data rapidly — token bucket allows initial burst then throttlesforiin {1..15};do
curl -s http://localhost:4000/api/data
echo""done
# Check live stats after sending requests
curl http://localhost:4000/admin/gateway-stats
# Check configured policies (includes algorithm per route)
curl http://localhost:4000/admin/rate-limit-rules
Run Tests
cd gateaway
npm test
✓ allows a request under the global limit
✓ blocks a request that exceeds the global IP limit
✓ blocks /auth/login after 5 requests (route limit) ← slidingWindow
✓ allows /auth/login when under the route limit ← slidingWindow
✓ sets X-RateLimit-* headers on allowed responses
✓ sets Retry-After header when blocked
✓ applies per-user check when x-user-id header is present
✓ allows traffic when Redis is down and REDIS_FAILURE_MODE=open
✓ blocks traffic when Redis is down and REDIS_FAILURE_MODE=closed
✓ applies api_data policy to /api/data/:id (prefix match) ← tokenBucket
Tests 10 passed (10)
How It Works
Every proxied request runs three sequential checks. A request is stopped as soon as it fails any tier.
Request
│
├─► 1. GLOBAL IP CHECK (fixedWindow)
│ identifier: client IP
│ limit: 300 req / 60s — applies to every route
│ fail → 429 { scope: "global_ip" }
│
├─► 2. PER-USER CHECK (fixedWindow, only if x-user-id header present)
│ identifier: x-user-id value
│ limit: 500 req / 60s
│ fail → 429 { scope: "global_user" }
│
└─► 3. ROUTE-LEVEL CHECK (algorithm chosen per route in limits.js)
/auth/login → 5 req / 60s slidingWindow (no boundary exploit)
/auth/register → 10 req / 60s slidingWindow
/api/data/* → 100 req / 60s tokenBucket (burst-tolerant)
/users/* → 60 req / 60s fixedWindow
other paths → skip tier 3, pass through
fail → 429 { scope: "ip_route", route: "...", algorithm: "..." }
✅ All checks passed → set X-RateLimit-* headers → proxy to backend → return response
Redis Key Patterns
# Fixed window — integer, self-deletes when TTL expires
rl:fw:ip:global:{ip}:{window}
rl:fw:user:global:{userId}:{window}
rl:fw:ip:route:{routeKey}:{ip}:{window}
# Sliding window — sorted set, timestamps pruned on every request
rl:sw:ip:route:{routeKey}:{ip}
# Token bucket — hash with { tokens, lastRefill }, refilled on every request
rl:tb:ip:route:{routeKey}:{ip}
A scalable API gateway built with Node.js and Redis featuring distributed rate limiting, request throttling, traffic control, and multi-layer protection using sliding window and token bucket algorithms.