Skip to content

Choose the right limiter: listener accept limits, connection caps, an external rate limit service, per-route token buckets, or per-user limits.

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.

LimiterAttaches toLimitsOn limit
Listener localListenerNew connections per intervalConnection dropped
Connection limitFilter chainConcurrent connectionsClosed, optionally after a delay
Network globalFilter chainNew connections, via external RLSConnection dropped
HTTP localHTTP filter / routeRequests per intervalHTTP 429
UserHTTP filterRequests per userHTTP 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.5s

Network 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/; done
200
200
429

Limits

  • 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.

Continue

Start typing to search the site.

↑ ↓ to move Enter to open Esc to close