Per-Tenant Quota Isolation
Quota isolation on a multi-tenant platform is a key-design problem before it is a rate-limiting problem. Get the key right and every tenant has an independent limit for free; get it wrong and one tenant’s growth becomes another tenant’s outage, with nothing in the configuration that looks incorrect.
Prerequisite concepts
This assumes the tenant identification and isolation-level material in multi-tenant routing strategies and the counter mechanics in rate limiting and throttling strategies.
Three levels, three different guarantees
# Envoy 1.32+ — descriptors built from verified values, tenant first
rate_limits:
- actions:
- request_headers: { header_name: "x-tenant", descriptor_key: "tenant" }
- request_headers: { header_name: "x-consumer-id", descriptor_key: "consumer" }
- generic_key: { descriptor_value: "orders" }
# the limit service: a per-tenant-per-consumer limit under a per-tenant ceiling
domain: platform
descriptors:
- key: tenant
descriptors:
- key: consumer
rate_limit: { unit: minute, requests_per_unit: 600 } # per integration
rate_limit: { unit: minute, requests_per_unit: 5000 } # tenant ceiling
Both headers must be set by the gateway from verified claims and stripped from inbound requests, or a tenant can spend another tenant’s quota by asserting their identifier — the failure described in multi-tenant routing strategies.
Shared capacity is still shared
Making a 429 useful to the tenant
A rejection that does not say which limit was hit produces a support ticket. Return the headers, and include enough detail for the tenant to distinguish their own integration’s limit from their organisation’s ceiling.
HTTP/1.1 429 Too Many Requests
retry-after: 12
x-ratelimit-limit: 600
x-ratelimit-remaining: 0
x-ratelimit-reset: 1754236800
x-ratelimit-scope: consumer # or: tenant
The scope header is the one that saves the conversation. Without it, a tenant whose integration is throttled while their overall usage is well under the ceiling has no way to tell whether the problem is theirs, another team’s inside their organisation, or the platform’s.
Decision matrix
| Complaint | Missing key component |
|---|---|
| “Another customer’s traffic throttles us” | tenant |
| “Our batch job starves our web app” | consumer within tenant |
| “We are throttled below our stated limit” | quota shared across regions, or a hash collision |
| “We see 429s with plenty of quota left” | a global ceiling is engaging — say so in the scope header |
Gotchas and failure signals
Per-region counters multiply the effective limit by the region count. Decide whether the published quota is global or regional and say which in the documentation.
A tenant identifier with high cardinality in a metric label will overwhelm the metrics store long before the rate limiter notices. Label metrics with a tenant tier or a sampled subset, not with every identifier.
Quota changes need to take effect without a deploy, or every tier upgrade becomes a release. Read limits from a store the gateway watches.
The first tenant onboarded with no limit at all is a permanent liability. Default new tenants to the smallest tier and raise deliberately.
Bursts, and why a per-minute limit is not what tenants experience
A quota expressed per minute says nothing about what happens in the first second of that minute, and the difference is what tenants actually notice.
With a fixed window, a tenant allowed five thousand requests a minute can send all five thousand in the first second, receive them all, and then see every request rejected for the remaining fifty-nine. From the platform’s perspective the quota was honoured exactly. From the tenant’s perspective the API was available for one second in sixty, and from the upstream’s perspective it received a spike five thousand requests tall.
A sliding window smooths the accounting and a token bucket smooths the delivery, which is the one that changes what the tenant feels: a refill rate with a bounded burst allowance lets a legitimate burst through while pacing sustained traffic. Publish both numbers — the sustained rate and the burst — because a tenant who only knows the per-minute figure will design a client that sends it all at once.
Validation
- Key includes tenant and consumer, both from verified claims
- Inbound tenant and consumer headers stripped at the edge
- Global ceiling exists beneath the per-tenant limits
- 429 responses carry limit, remaining, reset and scope
- Sum of allocated quotas monitored against real capacity
- Quota changes applied without a gateway deploy
FAQ
What belongs in the rate limit key?
The route, the tenant, and the consumer within the tenant. Route alone gives one shared bucket for the whole platform. Adding the tenant isolates customers from each other, which handles the first complaint. Adding the consumer stops one integration inside a tenant from consuming that tenant’s whole allowance, which is the second complaint and arrives about a month later.
Do per-tenant quotas protect the platform?
No — they protect tenants from each other. Forty tenants each allowed five thousand requests a minute permit two hundred thousand against a platform that may serve sixty thousand. Quotas are not reservations, and the gap is normal over-subscription. A global ceiling underneath the per-tenant limits is what protects capacity, and it should shed proportionally to consumption rather than first-come.
What should a 429 tell the tenant?
The limit, what remains, when it resets, and crucially the scope that was hit. Without a scope header a tenant whose integration is throttled while their overall usage sits well below their ceiling cannot tell whether the cause is their own app, another team in their organisation, or a platform-wide ceiling — and that ambiguity is the entire support conversation.
Should quotas be global or per region?
Decide and then document it, because per-region counters multiply the effective limit by the number of regions and consumers will eventually notice. Regional counters are cheap and approximate; a global counter is exact and puts a cross-region hop on the request path. Most platforms use regional counters with a global backstop, and state in the documentation that the published limit is enforced per region.
Parent: Multi-Tenant Routing Strategies
Related
- Multi-Tenant Routing Strategies — tenant identification and the isolation levels these keys implement.
- Rate Limiting & Throttling Strategies — the counter mechanics and window algorithms underneath.
- Tyk vs Envoy Global Rate Limit Service — where these descriptors are actually evaluated.