A parte mais comum de código de integração — o laço que tenta de novo — já vem pronta nos SDKs oficiais do Jev. Vale saber exatamente o que ela faz, porque os padrões são razoáveis para a maioria dos casos e errados para dois ou três.
Se você chama a API HTTP direto, nada disto acontece sozinho: a referência recomenda backoff exponencial em 429 e 529, e a implementação é sua. A chamada crua está em a API HTTP sem SDK.
Os padrões, lado a lado
| Configuração | Python | JavaScript |
|---|---|---|
| Novas tentativas | max_retries = 2 | maxRetries: 2 |
| Primeiro atraso | backoff_initial = 0.5 s | backoffInitialMs: 500 |
| Atraso máximo | backoff_max = 5.0 s | backoffMaxMs: 5000 |
| Jitter | backoff_jitter = 0.25 | backoffJitter: 0.25 |
| Status repetidos | 408, 429 e 500 a 599 | 408, 429 e 500 a 599 |
Respeita Retry-After | respect_retry_after = True | sim, com teto de maxRetryAfterMs: 60000 |
| Erro de conexão | api_connection_error = True | apiConnectionError: true |
| Tempo esgotado | api_timeout_error = True | apiTimeoutError: true |
| Orçamento por chamada | timeout = 30.0 s | tempo limite por tentativa, no cliente |
No Python há ainda a constante DEFAULT_TIMEOUT, de 10,0 segundos por operação
HTTP, que é diferente do orçamento total de retentativa.
Como ler cada parâmetro
max_retries é o número de tentativas depois da primeira. Com o padrão
2, o pior caso são três idas ao servidor. Zero desliga a repetição.
O backoff dobra. Começa em 0,5 segundo, vai a 1, depois 2, até o teto de 5 segundos. É o crescimento exponencial que a referência recomenda em 429 e 529.
O jitter evita a onda. Uma fração de 0,25 de cada atraso é subtraída aleatoriamente. Sem isso, cem processos que falharam no mesmo segundo voltariam juntos no mesmo segundo seguinte, e o servidor levaria a mesma rajada de novo.
A lista de status é a parte mais importante. Repetem 408, 429 e toda a faixa 500 a 599. Não repetem 401, 403, 404 e 422 — porque são erros do pedido, e a décima tentativa devolve o mesmo resultado. O detalhamento está em erros e exceções.
Retry-After ganha do seu backoff. Quando o servidor diz quanto esperar, o
SDK obedece. O teto de 60 segundos do lado JavaScript existe para o caso de um
pedido longo demais: acima disso, ele usa o próprio backoff.
O orçamento total é o que protege o seu serviço. Em Python, timeout = 30.0
limita a chamada inteira do SDK, incluindo a primeira tentativa e as esperas.
Sem esse teto, três tentativas com backoff podem segurar uma requisição bem
mais tempo do que a sua API tem para responder.
Configurar em Python
from typesafe_sdk import RetryPolicy, TypeSafeClient
client = TypeSafeClient(
retry=RetryPolicy(
max_retries=3,
timeout=10.0,
http_statuses={429, 500, 502, 503, 504},
)
)
Configurar em JavaScript
import { TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient({
timeout: 8000,
retry: { maxRetries: 3, backoffInitialMs: 250, backoffMaxMs: 3000 },
});
Sobrescritas parciais herdam os campos que você não informou, do cliente ou dos
padrões do SDK. Ou seja, mexer em maxRetries não zera o resto.
Três situações em que o padrão não serve
Caminho síncrono na frente de um usuário. Se a sua API promete responder em
um segundo, um orçamento de 30 segundos é inaceitável: você vai segurar a
conexão e estourar o tempo limite de quem chamou você. Reduza
max_retries para 1 e o orçamento para algo próximo do seu contrato de
latência — nas nossas cinco medições de 18 de setembro de 2026, medidas de fora
e incluindo rede, a ida e volta ficou entre 270 e 802 milissegundos, então um
orçamento de dois ou três segundos já cobre uma repetição.
Processamento em lote, à noite. Aqui é o contrário: falhar rápido não traz
benefício nenhum. Aumente max_retries, aumente o teto de backoff e deixe o
trabalho terminar.
Fila com muitos trabalhadores em paralelo. Neste caso a retentativa do SDK não basta, porque o problema é agregado: se todos os trabalhadores batem no limite de taxa, repetir individualmente só redistribui a rajada. A solução é controlar o paralelismo antes da chamada, e o assunto está em limites de taxa.
Um erro que o backoff não conserta
Repetir resolve falha transitória. Não resolve nada quando o problema é o tamanho da requisição, o formato do corpo ou a pergunta mal escrita. Se a mesma chamada falha sempre, a resposta está no corpo do erro, não no número de tentativas.
E vale lembrar do lado do custo: cada tentativa que chega ao servidor consome tokens de entrada. Uma política agressiva demais em um lote grande aparece na fatura, e a conta está em quanto custa uma decisão.
Para os dois SDKs por inteiro, veja SDK Python e SDK JavaScript. O índice está em como usar.
Perguntas frequentes
Preciso escrever a minha própria retentativa?
Com os SDKs oficiais, não. A política padrão documentada faz até 2 novas tentativas, com backoff inicial de 0,5 segundo dobrando até 5 segundos, jitter de 0,25, repetindo nos status 408, 429 e 500 a 599 e respeitando o Retry-After. Chamando a API HTTP direto, sim: aí a repetição é sua.
O que é o jitter de 0,25?
É a fração de cada atraso de backoff que é subtraída de forma aleatória. Serve para que muitos clientes que falharam ao mesmo tempo não voltem todos no mesmo instante, o que criaria uma nova onda de erro.
O que acontece se o servidor mandar Retry-After?
O SDK obedece, porque respect_retry_after vem ligado por padrão. No SDK de JavaScript há um teto: atrasos pedidos acima de 60.000 milissegundos caem de volta para o backoff próprio.
Qual é o tempo limite padrão?
No SDK Python, a constante DEFAULT_TIMEOUT é 10,0 segundos por operação HTTP, e a RetryPolicy tem um orçamento total de 30,0 segundos por chamada, incluindo a primeira tentativa e as esperas. No JavaScript, o timeout é por tentativa e configurável no cliente.
422 entra na retentativa?
Não, e isso é proposital. A lista padrão de status repetidos é 408, 429 e 500 a 599. Um 422 é corpo inválido: repetir sem mudar nada devolve o mesmo erro e gasta cota.
Como eu desligo a retentativa?
Com max_retries igual a zero, em Python, ou maxRetries igual a zero, em JavaScript. Faz sentido em um caminho síncrono com orçamento de tempo muito apertado, onde falhar rápido é melhor do que esperar.