Skip to main content
Requests are limited by client IP using the Redis-backed go-limiter store, so the budget is shared by every application replica rather than being per-process. IPv6 addresses are bucketed by their /64 network, so a client cannot rotate addresses within the same network to obtain a fresh budget.

Budget size

Direct connections

When clients connect directly to the service, leave both proxy settings unset. The TCP peer address is the client.

Behind a reverse proxy

Behind a proxy you must set both of these: the header the proxy writes, and the CIDRs of every trusted proxy that can connect to this service.
Startup rejects either setting on its own. Configuring one without the other is treated as a misconfiguration, not a partial setup.
The forwarding header is ignored unless the TCP peer (r.RemoteAddr) belongs to that CIDR allowlist. Without this, any client could spoof the header and be rate-limited as someone else, or as nobody.

How the client is resolved

For X-Forwarded-For, the limiter walks the chain from right to left, skips trusted proxy addresses, and uses the first untrusted address as the client. Two things this requires of your infrastructure:
  • Your reverse proxy must append the address of its direct peer to the header.
  • The service must not be reachable from the public internet outside the configured CIDRs.

Single-value headers

For a header such as CF-Connecting-IP that carries one address rather than a chain, configure the CDN or edge proxy CIDRs and ensure the edge overwrites the inbound header on every request. Otherwise a client can supply its own.

Failure behaviour

An absent or malformed forwarding header falls back to the known proxy address. That fails closed, so several clients may share a budget, rather than trusting a value an attacker controls.