Skip to content

Rate limiting

Token-bucket rate limits live under [security.rate_limit] (global), [domains.security.rate_limit] (per domain), and [domains.routes.security.rate_limit] (per route). Dynamic.

Per-domain and per-route blocks are whole-block replaces: the most specific scope that defines a rate_limit block replaces the parent’s block entirely. There is no field-level inheritance.

See examples/config/rate-limit-example.toml on GitHub for a full file.

Key limit_by values:

  • ip: client IP (resolved from X-Forwarded-For when [security].trusted_proxies is set; see below)
  • header: value of a named header (limit_by_header)
  • route: shared limit per route path
  • combined: IP + route

Responses use 429 when exceeded. Counters are in-memory and per process; they are not shared across replicas.

When the proxy sits behind a trusted load balancer, set [security].trusted_proxies (a global CIDR list) so limit_by = "ip" and "combined" resolve the real client IP from X-Forwarded-For instead of the proxy’s IP:

security:
trusted_proxies:
- "10.0.0.0/8"
- "172.16.0.0/12"
rate_limit:
enabled: true
requests_per_second: 500
burst: 1000
limit_by: "ip"

trusted_proxies is global only: it is a property of the network topology, not of any individual domain or route.

security:
rate_limit:
enabled: true
requests_per_second: 1000
burst: 2000
window_seconds: 1
limit_by: "ip"

The domain block replaces the global rate-limit config entirely for all requests that match this domain.

domains:
- host: "api.example.com"
security:
rate_limit:
enabled: true
requests_per_second: 50
burst: 100
limit_by: "combined"

The route block replaces the domain (or global) rate-limit config for requests matching this route.

domains:
- host: "api.example.com"
routes:
- prefix: "/api"
backend: "backend-a:9000"
security:
rate_limit:
enabled: true
requests_per_second: 50
burst: 100
limit_by: "combined"
- prefix: "/public"
backend: "backend-b:9000"
security:
rate_limit:
enabled: false
security:
rate_limit:
enabled: true
requests_per_second: 200
burst: 400
limit_by: "header"
limit_by_header: "X-API-Key"