Vishal.dev
Back
4.5k/s
Backend

throttleGate — Production-Grade API Gateway

API gateway built from scratch with custom Lua rate-limiting algorithms (token bucket + sliding window log) executed atomically in Redis, Hystrix-style circuit breaking, dynamic service discovery, distributed tracing, and hot-reloadable config.

Node.js 20Express 4TypeScriptRedis 7LuaOpenTelemetryPrometheusPinoZodhttp-proxyVitestk6React 19Kubernetes
4.5k
req/s throughput
8ms
p50 latency
18
Prometheus metrics
16
Pipeline stages

Domain Knowledge

What problem this project solves

API gateways concentrate the hardest edge concerns: rate limiting must be accurate under concurrency (hence atomic Lua in Redis), circuit breaking must absorb upstream failures without cascading, and service discovery must track health in real time. throttleGate demonstrates each with measurable rigor — 4,500 req/s max throughput with p50 8ms, p95 45ms, p99 120ms.

Architecture

How the system is structured

A 16-step request pipeline: size limiter → slow-request protection → IP filter (CIDR) → input sanitizer → CORS → tracing → health/metrics → body parse → registration → stacked Lua rate limiter → auth (API key/JWT) → request coalescer → circuit breaker → route match → load balancer → proxy with retry/backoff. Hot-reload rebuilds the router stack on config change.

Data Model

Schema design and data flow

Config-driven: a Zod schema with 63+ fields covering limits, tiers (Free/Pro/Enterprise), circuit breaker thresholds, health checks, and routing rules. Service registry entries live in Redis with active + passive health checks.

Key Challenges

Hardest problems encountered

Writing correct rate-limiting Lua was the core challenge — refill math, atomicity, TTL management, and fail-open behavior under Redis outages. The request coalescer dedupes identical GET/HEAD requests so 100 concurrent clients share one upstream call. Circuit breaker state is inherently local, so it runs in-process per route.

Scaling Strategy

How the system grows

Stateless gateway instances scale horizontally behind Kubernetes (HPA 2-10, PDB min 2). Redis holds shared state — rate limits, registry, config. Weighted round-robin + least-connections load balancing distributes traffic. Bulkheading isolates connection pools per upstream.

Security

Defense-in-depth approach

IP allowlist/denylist with CIDR, request-smuggling detection, slow-loris protection, oversized-payload DoS protection, XSS/SQLi sanitizer, API key + JWT auth with tenant extraction, and rate limits on every dimension.

Failure Handling

Resilience and recovery

Fail-open mode when Redis is down (configurable), retry with exponential backoff + jitter for idempotent methods only, dead-letter circuit breaker transitions, and graceful shutdown on SIGTERM/SIGINT.

Observability

Monitoring and debugging

18 Prometheus metrics across 6 groups (proxy, rate limit, circuit breaker, security, service discovery, coalescer) plus OpenTelemetry spans, Pino logs, and a React dashboard (6 pages, 15 Radix components, Recharts).

Trade-offs

Engineering decisions and alternatives

Custom Lua over npm rate-limit packages for atomicity and performance. In-process circuit breakers over centralized state. Sliding-window-log over fixed-window (no boundary spikes). No retry for POST by default (idempotency only). Express over Fastify for ecosystem maturity.

Architecture Decisions

Key choices and what was rejected

Decision
Chosen
Rejected
Rate limiting
Atomic Redis Lua (token bucket + SWL)
npm rate-limit packages
Failure posture
Fail-open when Redis is down
Fail-closed (outage amplifies)
Retries
Idempotent methods only
Retry all methods
Breakers
In-process per route
Centralized state

Senior-Level Topics

Concepts this project explores

Redis Lua ScriptingRate Limit AlgorithmsCircuit BreakersService DiscoveryDistributed TracingHot-Reload ConfigLoad BalancingBulkheading