Arion has five rate limiters, each guarding a different layer. Pick by what you need to protect: the accept loop, concurrent connections, a shared quota across proxies, request throughput, or individual users.
| Limiter | Attaches to | Limits | On limit |
|---|---|---|---|
| Listener local | Listener | New connections per interval | Connection dropped |
| Connection limit | Filter chain | Concurrent connections | Closed, optionally after a delay |
| Network global | Filter chain | New connections, via external RLS | Connection dropped |
| HTTP local | HTTP filter / route | Requests per interval | HTTP 429 |
| User | HTTP filter | Requests per user | HTTP 429 |
All local limiters share the same token-bucket shape: max_tokens is the burst size, and tokens_per_fill tokens return every fill_interval.
Listener local rate limit
A listener filter that drops connections above the bucket rate before any filter chain work happens — the cheapest place to shed an accept flood:
listener_filters:
- name: envoy.filters.listener.local_ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.local_ratelimit.v3.LocalRateLimit
stat_prefix: listener_rl
token_bucket: { max_tokens: 100, tokens_per_fill: 100, fill_interval: 1s }Connection limit
A network filter that caps concurrent connections on a filter chain with one process-wide counter. delay holds excess connections open before closing them, which slows down flooders:
filters:
- name: envoy.filters.network.connection_limit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit
stat_prefix: cx_limit
max_connections: 1000
delay: 0.5sNetwork global rate limit
A network filter that asks an external rate limit service (gRPC) about every new connection, so one quota spans a whole fleet. When the RLS response carries a quota, Arion caches it for the quota window and answers locally until it is spent:
filters:
- name: envoy.filters.network.ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.ratelimit.v3.RateLimit
stat_prefix: global_rl
domain: api.example.com
failure_mode_deny: true
descriptors:
- entries:
- { key: destination_cluster, value: api }
rate_limit_service:
grpc_service:
envoy_grpc: { cluster_name: rls }
On listeners with a TLS inspector, domain may be omitted: the connection's SNI becomes the RLS domain, giving each tenant its own quota namespace with no per-tenant config. Without the inspector, domain is required and the config is refused otherwise.
HTTP local rate limit
An HTTP filter with a token bucket per filter instance, returning 429 (configurable via status) above the rate. A route can override the bucket through typed_per_filter_config, so different routes get different budgets:
http_filters:
- name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
stat_prefix: http_rl
token_bucket: { max_tokens: 50, tokens_per_fill: 50, fill_interval: 1s }User rate limit
An Arion-native HTTP filter that keys buckets on a request header identifying the caller. Entries with a user_id pin a limit to that user; the entry without one is the default for any other identified caller, and requests missing the header pass through unlimited. simple_rate_limit is shorthand for a bucket of max_tokens refilling at rate tokens per second:
http_filters:
- name: arion.filters.http.user_rate_limit
typed_config:
"@type": type.googleapis.com/arion.extensions.filters.http.user_rate_limit.v3.UserRateLimiter
user_id_header_name: x-api-key
user_rate_limits:
- user_id: "premium-key"
simple_rate_limit: { max_tokens: 100, rate: 100 }
- simple_rate_limit: { max_tokens: 5, rate: 5 }Verify
With a small bucket (max_tokens: 2), exhaust it and watch the status flip:
for i in 1 2 3; do curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/; done200
200
429Limits
- Local buckets live in one Arion process; use the network global filter when a quota must span replicas.
- Global rate limiting is network-level only; the HTTP global rate limit filter is not supported.
- RLS descriptors are static key/value pairs; dynamic entries from request attributes are not supported.
- The RLS cluster must speak HTTP/2 (gRPC).
- The user rate limiter only limits requests that carry the user-id header; the default entry applies to identified users without their own entry.
Each limiter's full field table is on its reference page, linked above; the connection limit reference covers the counter semantics.