Skip to content

Rate limits

Sliding-window rate limits protect upstream providers and share capacity fairly across clients.

More important than the numbers: build your integration so bursts, retries, and background jobs don't fight each other.

Current limits

Tier Beta Production
Per Keycloak client (azp) 2,000 req/min 10,000 req/min
Per provider (route prefix) 500 req/min 2,000 req/min
Global (whole API) 5,000 req/min 20,000 req/min

Each request counts against all three tiers. Exceed any one → 429 Too Many Requests.

429 response

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/problem+json

{
  "type": "https://tools.ietf.org/html/rfc6585#section-4",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded for client 'agentins'.",
  "retry-after-seconds": 30
}

When Retry-After is present, always respect it.

Retry strategy

On 429 and transient 5xx → exponential backoff with jitter, not immediate retries.

retry_delay = base_delay * 2^attempt + random_jitter

With 1s base delay, capped at 60s:

Attempt Delay
1 1s + jitter
2 2s + jitter
3 4s + jitter
4 8s + jitter
5 16s + jitter
6+ capped at 60s

If retries keep failing, stop and surface it to your monitoring/on-call flow.

C# example

async Task<HttpResponseMessage> SendWithRetryAsync(HttpRequestMessage req)
{
    var maxAttempts = 6;
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
        var resp = await _http.SendAsync(req);
        if (resp.StatusCode != HttpStatusCode.TooManyRequests &&
            resp.StatusCode != HttpStatusCode.ServiceUnavailable)
            return resp;

        var retryAfter = resp.Headers.RetryAfter?.Delta
                         ?? TimeSpan.FromSeconds(Math.Pow(2, attempt));
        var jitter = TimeSpan.FromMilliseconds(Random.Shared.Next(0, 1000));
        await Task.Delay(retryAfter + jitter);
    }
    throw new InvalidOperationException("Rate limit retries exhausted");
}

Best practices

What works

  • Cache lookup data (brands, countries, static parameters)
  • Queue or stagger background jobs instead of firing them all at once
  • Monitor your 429 rate in production
  • Batch where the flow allows it

What usually breaks

  • Tight retry loops
  • Polling every few hundred ms
  • Direct frontend → API calls without buffering

Need higher limits?

Send to Support:

  • Your client_id
  • Expected peak throughput
  • Traffic pattern
  • Short business context for the workload