Command Palette
Search for a command to run...
A rate limiter built in Go
This project implements a fixed-window counter with RAM and Redis storage. Use it as a Go library or run its reverse proxy in front of an HTTP backend to check each request against a configured allowance.
How a request moves through the system
The gateway matches a route to a policy, resolves the caller’s identity, and checks its counter. Requests within the limit reach the upstream. Once the allowance is exhausted, the gateway returns 429 with a Retry-After header without calling the backend.
- 01
Match a policy
Routes select the limit, window, identity type, and policy revision.
- 02
Check the counter
A tenant, policy, identity, and optional route identify the allowance.
- 03
Forward or reject
Admitted attempts consume quota, even if the upstream later fails.
One algorithm, two storage modes
RAM for a single process
Counters live in the gateway’s memory. Concurrent access is synchronized, keys are bounded, and expired entries are cleaned up. Each process has its own allowance, and a restart clears its counters.
Redis for shared quotas
Replicas share counters using the same namespace and policy settings. A Lua script checks capacity, updates the counter, and sets expiry atomically on Redis. Storage failures return 503 without forwarding or falling back to RAM.
Identity and policy boundaries
Policies can limit by client IP, verified user ID, or verified API credential ID. Tenant and policy identifiers separate allowances; optional route grouping uses canonical route patterns rather than raw URLs. User and credential identities require verified authentication. Forwarded IP headers are accepted only from configured trusted proxies.
The reverse proxy loads a versioned JSON configuration at startup. It controls routes, upstream address, rate limits, key capacity, timeouts, and storage. The published Docker image includes the gateway and a demo backend for trying the request flow locally.
Understand the fixed-window tradeoff
Each identity receives a new allowance when its window resets. A client can use one allowance just before a boundary and another just after it, creating a short burst. This implementation checks one policy per request; it does not combine several policies into one atomic decision. Redis provides shared counters, while RAM remains local to each gateway.