# Rate Limits

Bound public and authenticated API routes with gateway-enforced per-minute token buckets and explicit retry responses.

Route limits protect application capacity and abuse-sensitive actions before a
request reaches domain code. Define stricter limits for login, reset, webhook,
checkout, and public write routes than for cached content.

## Attach a route limit

Set `rate_limit_per_min` on an API route. The Gateway applies a token bucket to
the matching prefix before it publishes a request to your application.

```json filename="ferrite.json"
{
  "services": [{ "name": "account-requests", "primitive": "queue" }],
  "applications": [{
    "name": "accounts",
    "artifact_key": "apps/accounts@v1",
    "artifact_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
    "bindings": [
      { "handle": "requests", "kind": "queue", "service": "account-requests" }
    ],
    "routes": [{
      "prefix": "/api/auth/login",
      "binding": "requests",
      "kind": "api",
      "rate_limit_per_min": 10
    }]
  }]
}
```

When the bucket is empty, the Gateway returns `429` with `Retry-After: 60` and
does not publish the protected request. Values must be between 1 and 1,000,000
and are valid only on API routes.

## Authentication limits

The route bucket is a capacity boundary, not a complete identity-aware abuse
policy. Authentication code should also use generic outward responses,
comparable password work for unknown identifiers, account and network keys,
resend quotas, and exponential delay. Avoid permanent lockout that an attacker
can trigger for another user.

## Test the boundary

Exercise the exact budget and refill boundary, concurrent requests, a Gateway
restart, and more-specific routes beside a catch-all API route. Confirm that
rejected requests do not reach the protected effect. Test the separate
identity-aware abuse policy with account and network variations.

See [Authentication](/developers/authentication/) and [Reliability](/developers/reliability/).
