Tyk vs Envoy Global Rate Limit Service
Both Tyk and Envoy can enforce a quota that is exact across a whole fleet, and both do it by asking a shared service. The differences are in what that service is, who runs it, and what happens when it is slow — which turns out to matter more than the algorithm either uses. This page compares the two designs on those grounds.
Prerequisite concepts
This assumes the algorithm and state-placement material in rate limiting and throttling strategies, and the shared-counter mechanics in dynamic rate limiting with Redis backends.
Two shapes of the same idea
# Envoy 1.32+ — the proxy sends descriptors; the service decides
- name: envoy.filters.http.ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
domain: public_api
timeout: 0.05s # 50 ms — the budget for the decision
failure_mode_deny: false # allow when the service is unreachable
rate_limit_service:
grpc_service: { envoy_grpc: { cluster_name: ratelimit } }
transport_api_version: V3
# per route, what to send as the key
rate_limits:
- actions:
- request_headers: { header_name: "x-consumer-id", descriptor_key: "consumer" }
- generic_key: { descriptor_value: "orders_write" }
# the service's own configuration — where the numbers live
domain: public_api
descriptors:
- key: consumer
descriptors:
- key: generic_key
value: orders_write
rate_limit: { unit: minute, requests_per_unit: 600 }
- key: generic_key
value: orders_write
rate_limit: { unit: minute, requests_per_unit: 20000 } # global backstop
The two-level descriptor structure is the feature worth noticing: a per-consumer limit and a global ceiling for the same route, evaluated in one call. Tyk expresses the equivalent by combining a policy-level quota with a global one, configured in the API definition rather than in a separate service.
The failure question
Latency, and where the call sits
Both designs add a network round trip before the request is forwarded. The Envoy timeout is explicit and short by convention — tens of milliseconds — because the decision blocks the request. Tyk’s Redis call has the same property with its own timeout configuration. In both cases the limiter should be the closest network dependency the request has, ideally in the same availability zone.
Decision matrix
| If you want | Choose |
|---|---|
| Limits configured with the API definition | Tyk |
| Limits owned by a separate service and team | Envoy plus a rate limit service |
| Graceful degradation under store failure | Tyk’s local fallback |
| Behaviour that can be stated in one sentence | Envoy’s explicit failure mode |
| Multi-level limits in a single decision | Envoy descriptors |
| One fewer component to operate | Tyk |
Gotchas and failure signals
Descriptor design is the actual work in the Envoy model. A missing action means every consumer shares one bucket; a too-specific one means each consumer gets a bucket of one request. Test the descriptors, not just the limits.
Both designs make the limiter a dependency of every request. It needs a dashboard, a capacity plan and an alert on its own error rate — not only on the 429s it produces.
Local fallback silently changes the contract. A consumer that occasionally exceeds their published limit during a Redis blip is a support conversation you will have; decide now whether that is acceptable.
A limit expressed per minute allows the whole minute’s quota in the first second unless the algorithm smooths it. Check which window your configuration actually implements.
Where the limit is enforced also decides what a 429 means
A detail that only surfaces during an incident: the two designs disagree about what a rejected request has already cost.
In the Tyk model the gateway has read the request, resolved the consumer and consulted the store before deciding, so a rejected request has consumed a connection, an identity lookup and a network round trip. In the Envoy model the same is true, with the descriptor call in place of the store lookup. Neither is free, and at very high rejection rates — a misbehaving client hammering an endpoint — the limiter itself becomes the load.
The mitigation in both cases is a cheaper outer layer: a connection-rate limit or a per-IP request limit enforced locally, before any shared lookup happens. That layer is imprecise on purpose. Its job is not to enforce the published quota but to make the enforcement of the published quota affordable, by ensuring that the expensive, exact path only ever sees traffic that has already passed a cheap, approximate one.
Validation
- Limiter latency measured at p99 and inside the route budget
- Failure mode chosen, documented and exercised with the limiter stopped
- Descriptors or policies tested with two consumers, proving buckets are separate
- Limiter error rate alerted on independently of the 429 rate
- Limiter deployed in the same zone as the proxies that call it
- Burst behaviour within the window checked against what consumers expect
FAQ
What is the structural difference between the two?
Tyk keeps the limiting logic in each gateway and shares only the counter store, usually Redis. Envoy sends descriptors to a separate rate limit service that owns both the logic and the store. The consequence is where the numbers live: in an API definition alongside the route, or in a service configuration owned and deployed separately.
Which handles a degraded backend better?
They handle it differently rather than better. Tyk can fall back to per-node counters, so quotas keep applying with reduced accuracy and consumers may exceed their limit by up to the node count. Envoy applies failure_mode_deny: false means limits stop applying entirely, true means everything returns 429. Envoy’s behaviour is easier to state precisely; Tyk’s is more forgiving.
How much latency does a global limiter add?
One network round trip on every request, before it is forwarded. Same-zone that is around a millisecond and invisible. Cross-zone it is five to ten milliseconds, which is significant against a twenty-five millisecond gateway budget. Cross-region it dominates. The limiter should be the closest dependency the request has, with a regional limiter plus a global backstop as the usual compromise.
What is the hard part of the Envoy model?
Descriptor design. The proxy sends a set of key-value descriptors and the service matches them against its configuration; a missing action means every consumer shares one bucket, and an over-specific one gives each consumer a bucket of one. Test the descriptors with two consumers and prove the buckets are separate before trusting the limits.
Parent: Rate Limiting & Throttling Strategies
Related
- Rate Limiting & Throttling Strategies — algorithms and state placement behind both designs.
- Dynamic Rate Limiting with Redis Backends — the shared-counter mechanics in detail.
- Per-Tenant Quota Isolation — what the descriptors need to include on a multi-tenant platform.