Guia

Rate limit 429 e Retry-After

Como tratar 429 sem transformar retry em amplificador de erro.

Regras práticas

  • Respeite Retry-After quando presente.
  • Se o header não vier, aplique backoff exponencial com jitter.
  • Defina um teto de tentativas e registre a falha final.
  • Não rode retries paralelos para a mesma unidade de trabalho.

Exemplo de estratégia

ts
async function callWithRetry(input: RequestInfo, init: RequestInit, attempts = 5) {
  for (let attempt = 0; attempt < attempts; attempt += 1) {
    const res = await fetch(input, init);
    if (res.status !== 429) {
      return res;
    }

    const retryAfter = Number(res.headers.get("retry-after") ?? "0");
    const fallbackMs = Math.min(1000 * 2 ** attempt, 10000);
    const waitMs = retryAfter > 0 ? retryAfter * 1000 : fallbackMs + Math.random() * 250;
    await new Promise((resolve) => setTimeout(resolve, waitMs));
  }

  throw new Error("retry budget exhausted");
}

O que monitorar

  • quantidade de respostas 429 por integração
  • tempo médio até sucesso após retry
  • jobs que esgotam o orçamento de tentativas

Quando parar de insistir

Se o volume for previsivelmente alto, não esconda o problema atrás de retry infinito. Mude o fluxo para export assíncrono ou renegocie a cadência da integração.

Feche o ciclo

Retry seguro funciona melhor quando combinado com paginação estável e export assíncrono para picos.