# rate_limited

The per-IP request rate limit was exceeded; honour Retry-After (429).

## Meaning

Written before any handler runs, by the per-operation limiter in front of the API
operations, including the OAuth endpoints. Every rate-limited endpoint draws from
one budget per client IP: `rate_limit.rps` per second with bursts of
`rate_limit.burst` (memory backend), or `rps x window` per `rate_limit.window`
(redis backend). The response carries `X-RateLimit-Limit`,
`X-RateLimit-Remaining` and `Retry-After`.

## Impact

Requests from that address are refused until the window resets. A single client
looping is the usual cause. If many unrelated users are refused, the server likely
sees them all as one address behind a proxy.

## Diagnosis

1. Refusals are recorded as `auth.rate_limit.triggered` with reason `rate_limited`
   and `limit_scope` `request_rate`, coalesced per caller.
2. Compare the client address in the records with your proxies' addresses; check
   `security.client_ip.mode` and `security.trusted_proxies`.
3. `nauthera_rate_limit_degraded` reads `1` while a replica limits on its own.

## Mitigation

- As a client developer: wait for `Retry-After` before retrying, back off
  exponentially, and cache discovery documents and JWKS.
- As an operator: list your proxies in `security.trusted_proxies`; raise
  `rate_limit.rps` only for real traffic. See
  [Rate Limits](https://www.nauthera.io/docs/v1/rate-limits#rate-limiting).

## Escalation

Escalate when the limit trips well below the configured rate with proxies set up
correctly. Open an issue with request ids, the `rate_limit.*` and
`security.client_ip` settings and the server version.

---

[Problem code runbooks](https://www.nauthera.io/docs/v1/runbooks/problems) · Generated from [`internal/runbook/problems.yaml`](https://github.com/nauthera/nauthera-server/blob/main/internal/runbook/problems.yaml) in nauthera-server.
