Command Palette

Search for a command to run...

Rate Limiter · Overview

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.

  1. 01

    Match a policy

    Routes select the limit, window, identity type, and policy revision.

  2. 02

    Check the counter

    A tenant, policy, identity, and optional route identify the allowance.

  3. 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.

Start here