---
title: Rate limiting
description: Per-route rate limiting (enforced), plus the builder-only token-bucket limiter and the distributed, state-backed variant.
---

# Rate limiting

A route's `routes[].rate_limit` block is **enforced**: when any route declares a limit, the gateway
adds a route-aware limiter (`RouteRateLimiter`) to the request chain. The crate also ships a
full-featured token-bucket limiter (`octopus_middleware::RateLimit`) and a distributed variant for
embedded/library use.

<Callout type="info" title="What is enforced">
  **`routes[].rate_limit` is enforced.** The route-aware limiter applies a **fixed window per route**
  — keyed by the route's path pattern, so all requests matching a route (including wildcard paths)
  share one window — and returns `429 Too Many Requests` when the window is exceeded. The counter is
  currently held in an **in-process** state store (per replica); a shared backend (e.g. Redis) for
  cross-replica limits is planned.

  Not yet enforced: identity-based limiting (the auth gateway sets an `AuthRateLimitKey`, but nothing
  consumes it) and per-API-key `rate_limit` on `auth_providers` entries.
</Callout>

## `routes[].rate_limit`

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `requests_per_window` | int | _(required)_ | Requests allowed per window for the route |
| `window_size` | duration | _(required)_ | Window length (e.g. `1s`, `1m`) |

```yaml
routes:
  - path: /api/*
    upstream: backend
    methods: [GET, POST]
    rate_limit:
      requests_per_window: 100
      window_size: 1m
```

Durations use humantime syntax (`1s`, `500ms`, `1m`, `1h`). On the `429` response the limiter sets
`Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining: 0`, and `X-RateLimit-Reset`.

## The builder-only token-bucket limiter

`octopus_middleware::RateLimit` (built on the `governor` library) is a richer limiter available for
embedded/library use via the [builder](/docs/octopus/middleware#using-middleware-programmatically) — it is
**not** wired into the gateway binary. It supports:

### Strategies

| Strategy | Behavior |
| --- | --- |
| Token bucket (default) | Allows bursts up to the quota, refilled over the window |
| Fixed window | Simple per-window counter |

### Key extractors

| Extractor | Key source |
| --- | --- |
| Global (default) | A single shared limiter for all traffic |
| IP | Client IP address |
| Header | A configured header (e.g. an API-key header) |
| Path | The request path |
| Identity | The `AuthRateLimitKey` set by the auth gateway (`user:<id>`) |

It also supports a map of per-path limits with independent quotas.

### Distributed variant

With the crate's `distributed` feature, `DistributedRateLimit` backs a single limit with shared
state (`octopus-state`) so it holds across replicas. The route-aware `RouteRateLimiter` that enforces
`routes[].rate_limit` uses the same state abstraction (with an in-process backend today).

## Related

- [Routes](/docs/octopus/configuration/routes) — where `routes[].rate_limit` lives.
- [State](/docs/octopus/state) — the store behind shared rate-limit counters.
- [Middleware overview](/docs/octopus/middleware) — the request-chain order and wiring status.
