Skip to content

Rate Limiting

The rate_limit module provides a sliding-window rate limiter backed by ETS. It adds standard X-RateLimit-* headers to every response and returns 429 Too Many Requests when the limit is exceeded.

Basic usage

gleam
import mistweaver/rate_limit

router.scope("/api", [
  rate_limit.middleware(rate_limit.options(limit: 60, window_ms: 60_000))
], fn(r) { ... })

This allows 60 requests per minute per client IP, based on X-Forwarded-For (falling back to the raw host).

Options

gleam
pub type RateLimitOptions {
  RateLimitOptions(
    limit: Int,
    window_ms: Int,
    key_fn: fn(Conn(Connection)) -> String,
  )
}

options

gleam
rate_limit.options(limit: 100, window_ms: 60_000)

Creates options with the default IP-based key.

with_key

Override the key function to rate-limit by user ID, API token, or any other dimension:

gleam
rate_limit.options(limit: 1000, window_ms: 60_000)
|> rate_limit.with_key(fn(c) {
  case c.auth {
    Some(user) -> "user:" <> int.to_string(user.id)
    None -> c.request.host
  }
})

Response headers

Every response passing through the middleware gets:

HeaderValue
X-RateLimit-LimitThe configured limit
X-RateLimit-RemainingRequests remaining in the current window

A 429 response also includes:

HeaderValue
Retry-AfterSeconds until the window resets

Notes

The sliding window state is stored in-process ETS. It resets when the node restarts. For distributed rate limiting across multiple nodes, replace the key function's backing store with an external counter (Redis, Mnesia distributed table, etc.).

Released under the Apache 2.0 License.