Idempotency & Retry-Safe Systems · Retries Done Right

Retry Policies for Clients and SDKs

Ship safe defaults in your SDKs and document retry behavior for API consumers.

If you publish an API, your SDKs define how millions of clients retry. Good defaults: retry only retryable errors, 2–3 attempts, exponential backoff with jitter, honor Retry-After, automatically attach idempotency keys to unsafe requests (reused across that request's retries), respect an overall timeout, and expose hooks for logging. Document the policy so integrators without SDKs implement the same behavior.

SDK retry defaults

Setting Recommended default
Max retries 2–3
Backoff Exponential with full jitter, capped
Retryable Network errors, 408, 409 (in progress), 429, 5xx
Unsafe requests Auto Idempotency-Key, reused across attempts
Overall timeout Configurable (e.g., 60 s)
async request(method: string, path: string, body?: unknown, opts: { idempotencyKey?: string } = {}) {
  const key = method === "POST" ? opts.idempotencyKey ?? crypto.randomUUID() : undefined;  // one key for all attempts
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(this.base + path, {
      method, body: body && JSON.stringify(body), signal: AbortSignal.timeout(this.timeoutMs),
      headers: { "Content-Type": "application/json", ...(key && { "Idempotency-Key": key }) },
    }).catch((e) => e as Error);
    const status = res instanceof Error ? null : res.status;
    if (status !== null && status < 400) return (res as Response).json();
    if (attempt >= this.maxRetries || !shouldRetry(method, status, Boolean(key))) throw toApiError(res);
    await sleep(retryAfterMs(res) ?? fullJitter(attempt));
  }
}

Common pitfalls

  • SDKs that retry POST without keys.
  • A new key per attempt.
  • Hidden retries that users can't configure or observe.

Key points

  • Safe defaults in SDKs
  • Auto idempotency keys
  • Configurable and documented

Further reading: Stripe: Idempotency and retries

Practice questions

Why should an SDK generate the idempotency key before the first attempt?

Answer

All retries of that request must share the same key; generating it per attempt would make each retry a new operation.

Which errors should SDKs retry by default?

Answer

Network failures and timeouts, 408, 409 'in progress', 429 and 5xx — but unsafe methods only when an idempotency key is attached.

Open in the app to mark lessons complete, take notes and track your progress.