GuidesRate limits

Rate limits

Every operation on the platform is rate limited, with limits sized to each operation's sensitivity. Well-behaved clients never notice them.

How limiting works

  • Limits are per operation and per caller: keyed to your authenticated identity, or to the client IP for public endpoints.
  • Limits use a sliding window, so short bursts are fine and sustained flooding is not.
  • Exact numbers are tuned per operation and are deliberately not part of the contract; do not build to a specific number.

The 429 response

Exceeding a limit returns 429 with the standard error envelope and a Retry-After header with the number of seconds to wait. There are no X-RateLimit-* headers today; the honest contract is: on 429, wait Retry-After seconds.

Response, 429
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Try again shortly.",
    "requestId": "req_8c1d44e2a9f0"
  }
}

If the limiter itself is unavailable, sensitive operations fail closed with 503 RATE_LIMITER_UNAVAILABLE and a Retry-After. Treat it exactly like a 429 with a short wait.

Backing off well

Retry with backoff and jitter
async function withBackoff<T>(run: () => Promise<Response>): Promise<Response> {
  for (let attempt = 0; ; attempt++) {
    const res = await run();
    if (res.status !== 429 && res.status !== 503) return res;
    if (attempt >= 4) return res;
    const retryAfter = Number(res.headers.get("Retry-After") ?? 0);
    const backoff = Math.min(30_000, 500 * 2 ** attempt);
    const jitter = Math.random() * 250;
    await new Promise((r) => setTimeout(r, Math.max(retryAfter * 1000, backoff) + jitter));
  }
}
  • Always honour Retry-After when present, and add jitter so concurrent clients do not retry in lockstep.
  • Pair retries with an Idempotency-Key so retrying a write is always safe.
  • Cache reads you repeat, and batch where an operation allows it.
WhatsApp
Book a Call
Start Free