# Rate limiting

> Source: https://ferron.sh/docs/use-cases/security/rate-limiting

Ferron implements token bucket-based rate limiting with the `rate_limit` directive. This helps reduce brute-force login attempts and API abuse. When a client exceeds the configured rate, the server returns a `429 Too Many Requests` response with a `Retry-After` header.

## Protect login endpoints

Apply stricter limits to authentication paths than to the rest of the site:

```ferron
example.com {
    root /var/www/html

    # General traffic limit for the site.
    rate_limit {
        rate 50
        burst 100
        key remote_address
    }

    # Tighter limits for login endpoints.
    location /login {
        rate_limit {
            rate 5
            burst 10
            key remote_address
        }
    }

    location /api/auth {
        rate_limit {
            rate 5
            burst 10
            key remote_address
        }
    }
}
```

> [!note]
>
> - Rate limiting uses a token bucket algorithm: capacity = `rate + burst` tokens, refilled at `rate` tokens per second.
> - Ferron stores in-memory rate limit buckets in memory. They do not survive configuration reloads. Redis-backed buckets survive reloads.

> [!info]
>
> For distributed rate limiting across Ferron instances, configure a `rate_limit_backend` block with `type redis`. See [rate limiting configuration](https://ferron.sh/docs/configuration/content/rate-limit.md) for details. Redis failures allow by default (`fail_open true`), use `fail_open false` for high-security endpoints like login.

> [!important]
> If Ferron is behind another proxy/load balancer, make sure the client IP is correctly resolved. See [HTTP host directives](https://ferron.sh/docs/configuration/server/host.md) for `client_ip_from_header` configuration.

## Protect APIs with tiered limits

Use host-level and location-level limits together:

```ferron
api.example.com {
    location / {
        proxy http://localhost:3000

        # Default API limit.
        rate_limit {
            rate 100
            burst 200
            key remote_address
        }
    }

    # Heavier endpoints can have stricter caps.
    location /v1/search {
        rate_limit {
            rate 20
            burst 40
            key remote_address
        }
    }

    location /v1/login {
        rate_limit {
            rate 5
            burst 10
            key remote_address
        }
    }
}
```

> [!tip]
> Start with permissive values. Tighten them after you observe production traffic patterns. Keep login and token endpoints on stricter limits than read-only API endpoints.

## API key rate limiting

You can also key rate limits off request headers (for example, API keys):

```ferron
api.example.com {
    proxy http://localhost:3000

    rate_limit {
        rate 50
        burst 100
        key request.header.X-Api-Key
    }
}
```

Each unique API key gets its own token bucket, independent of the client IP.

## Throttling

To enable throttling for rate-limited requests, use the `throttle` subdirective:

```ferron
api.example.com {
    proxy http://localhost:3000
    rate_limit {
        rate 50
        burst 100
        key request.header.X-Api-Key
        throttle
    }
}
```

## JSON rate limit responses

By default, when a client exceeds the rate limit, Ferron responds with an HTTP `429 Too Many Requests` status code and includes an HTML-format message. You can customize this response to return a JSON object instead using `json_errors` directive:

```ferron
api.example.com {
    proxy http://localhost:3000
    rate_limit {
        rate 50
        burst 100
        key remote_address
    }
    json_errors
}
```