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
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
pub type RateLimitOptions {
RateLimitOptions(
limit: Int,
window_ms: Int,
key_fn: fn(Conn(Connection)) -> String,
)
}options
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:
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:
| Header | Value |
|---|---|
X-RateLimit-Limit | The configured limit |
X-RateLimit-Remaining | Requests remaining in the current window |
A 429 response also includes:
| Header | Value |
|---|---|
Retry-After | Seconds 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.).