Retry API: 7 padrões para chamadas externas resilientes
Falhas temporárias em APIs externas são inevitáveis. Este guia analisa 7 padrões de retry, do básico ao avançado, com critérios objetivos para você escolher o mais adequado ao seu cenário.
Falhas temporárias em APIs externas são inevitáveis. Este guia analisa 7 padrões de retry, do básico ao avançado, com critérios objetivos para você escolher o mais adequado ao seu cenário.
Falhas temporárias em chamadas de API externas são inevitáveis. Rede instável, timeout no servidor, limite de taxa atingido, qualquer um desses cenários derruba uma integração que, em condições normais, funciona bem. A pergunta não é se você vai precisar de retry, mas qual padrão vai usar para não transformar uma falha pontual em um efeito cascata.
Neste guia, analiso 7 padrões de retry para chamadas de API externas, do mais simples ao mais robusto. Para cada um, apresento o critério de uso, um exemplo concreto e a ressalva que todo mundo descobre depois de implementar. A especificação impressiona, o uso decide. No final, indico qual combinação faz mais sentido para cada tipo de integração.
1. Retry fixo (intervalo constante)
O padrão mais direto: após uma falha, espera-se um tempo fixo e tenta-se novamente. Por exemplo, 3 tentativas com intervalo de 2 segundos entre cada uma. É simples de implementar e fácil de debugar, mas tem um problema sério: se o serviço externo está sobrecarregado, todas as chamadas retornam no mesmo momento, criando uma onda de requisições que pode derrubar o servidor. Use retry fixo apenas quando o intervalo é curto e o número de tentativas é baixo, como em uma verificação de status que não é crítica. Em cenários de pico, o retry fixo amplifica a carga em vez de aliviá-la.
2. Retry com backoff exponencial
Em vez de esperar um tempo constante, o intervalo cresce a cada tentativa: 1s, 2s, 4s, 8s. A lógica é dar tempo ao serviço externo para se recuperar, reduzindo a pressão. É o padrão mais recomendado em documentações de provedores de API, incluindo o Azure Architecture Center, que trata o Padrão de Repetição como uma forma de lidar com falhas temporárias esperadas. O backoff exponencial resolve o problema do retry fixo, mas tem um ponto cego: sem um limite máximo de intervalo, você pode ficar esperando tempo demais entre tentativas e a resposta chega tarde para o usuário. Estabeleça um teto, por exemplo, no máximo 30 segundos entre tentativas, e um número máximo de tentativas, geralmente entre 3 e 5, conforme a recomendação de boas práticas em APIs.
3. Retry com jitter (aleatoriedade controlada)
O backoff exponencial sozinho ainda tem um problema: se várias instâncias da sua aplicação falham ao mesmo tempo, todas vão esperar exatamente 1s, 2s, 4s, e vão bater no serviço externo no mesmo instante. O jitter adiciona um valor aleatório ao intervalo de espera, por exemplo, entre 0 e 100ms a mais em cada tentativa. Isso espalha as requisições no tempo e reduz drasticamente a chance de uma rajada sincronizada. O jitter é barato de implementar e não muda a lógica de negócio. Use sempre que você tiver mais de uma instância da aplicação ou quando o serviço externo já apresenta erros de limite de taxa (HTTP 429).
4. Retry com limite de tempo total (deadline)
Sem um limite de tempo total, uma sequência de retries pode se arrastar por minutos, segurando threads e recursos. O padrão de deadline define um orçamento máximo, por exemplo, 10 segundos para todas as tentativas somadas. Se o tempo acabar, a chamada falha de vez. Isso é essencial em APIs síncronas que respondem para um usuário final. Um exemplo: uma chamada de pagamento que não pode esperar 30 segundos com backoff exponencial. O deadline força a falha rápida e permite que você retorne um erro amigável ou acione um fluxo assíncrono. Na prática, combine o deadline com o backoff exponencial, e não como substituto.
5. Retry seletivo por código HTTP
Nem toda falha merece retry. Erros 4xx, como 400 (requisição inválida) ou 401 (não autorizado), são permanentes e repetir não vai mudar o resultado. Erros 5xx, como 500 ou 503, indicam falha temporária do servidor, e o retry faz sentido. O padrão seletivo filtra os códigos de status antes de decidir tentar novamente. Isso evita desperdício de recursos e, mais importante, evita mascarar erros de configuração que deveriam ser corrigidos no código. Um exemplo: se a API retorna 429 (limite de taxa), o retry deve respeitar o header Retry-After, se presente, em vez de usar um intervalo fixo. Esse padrão exige que você conheça bem a API externa, mas é o que separa um retry inteligente de um retry cego.
6. Retry com circuit breaker
O circuit breaker interrompe as tentativas quando o número de falhas consecutivas ultrapassa um limite, por exemplo, 5 falhas em 10 segundos. Depois disso, a aplicação para de chamar o serviço externo por um período, digamos 30 segundos, e depois testa com uma única requisição. Se funcionar, o circuito fecha; se falhar, permanece aberto. Esse padrão protege o serviço externo de sobrecarga e também a sua aplicação, que deixa de gastar recursos com chamadas que provavelmente vão falhar. O circuit breaker é mais complexo de implementar, mas é o que dá resiliência de verdade em cenários de indisponibilidade prolongada. Sem ele, o backoff exponencial apenas adia o problema.
7. Retry com idempotência
Nem todo retry é seguro. Se a chamada original foi processada pelo servidor, mas a resposta se perdeu na rede, uma nova tentativa pode duplicar a operação. O padrão de idempotência garante que a segunda chamada não cause efeito duplicado. Na prática, envie um identificador único em cada requisição, como um header Idempotency-Key, e o servidor usa esse ID para reconhecer uma tentativa repetida e retornar a resposta original. Esse padrão é obrigatório em operações de escrita, como criação de pagamento ou envio de e-mail. Sem idempotência, o retry pode gerar cobrança duplicada ou e-mail enviado duas vezes. O custo é a complexidade de gerar e armazenar esses IDs, mas é o único jeito seguro de repetir uma operação não idempotente.
Qual padrão escolher na prática
Não existe um padrão único que sirva para tudo. Para leitura de dados, o backoff exponencial com jitter e limite de tempo já resolve a maioria dos casos. Para escrita, adicione idempotência e um circuit breaker para proteger contra falhas prolongadas. Para APIs com limite de taxa, o retry seletivo respeitando o header Retry-After é o mais eficiente. Comece simples, com backoff exponencial e jitter, e evolua conforme os erros reais aparecerem. O retry é uma ferramenta, não uma solução mágica. Pergunte se resolve sua vida antes de comprar a complexidade.
FAQ
Quantas tentativas de retry devo configurar?
Em geral, 3 a 5 tentativas é o intervalo mais comum em boas práticas de API. Menos que isso não dá tempo de o serviço se recuperar; mais que isso aumenta a latência e o risco de sobrecarga. Ajuste com base no tempo de resposta da API e no orçamento de tempo da sua chamada.
O que é jitter no contexto de retry?
Jitter é a adição de um valor aleatório ao intervalo de espera entre tentativas. Ele evita que várias instâncias da aplicação façam retry ao mesmo tempo, o que criaria uma rajada de requisições. O jitter é especialmente útil quando o serviço externo já está sob carga.
Qual a diferença entre backoff exponencial e circuit breaker?
O backoff exponencial aumenta o intervalo entre tentativas, mas continua tentando indefinidamente até o limite configurado. O circuit breaker interrompe completamente as tentativas após um número de falhas consecutivas, dando um tempo de descanso antes de testar novamente. O circuit breaker é uma proteção mais agressiva.
Devo fazer retry para erros 4xx?
Não, em geral. Erros 4xx indicam que a requisição está incorreta ou não autorizada, e repeti-la não vai mudar o resultado. Foque o retry em erros 5xx e em códigos como 429, que indicam falha temporária ou limite de taxa.
Como garantir que um retry não cause duplicação?
Use um identificador único, como um header Idempotency-Key, em cada requisição. O servidor reconhece o mesmo ID e retorna a resposta original em vez de processar novamente. Esse padrão é essencial para operações de escrita, como pagamentos.
O que é o header Retry-After?
O header Retry-After é enviado pelo servidor em respostas HTTP para indicar quanto tempo o cliente deve esperar antes de tentar novamente. É comum em respostas 429 (limite de taxa) e 503 (serviço indisponível). Respeitá-lo evita sobrecarregar ainda mais o serviço.
Letícia Sampaio Khoury
Editora de Gadgets e Consumo Tech
Testa o gadget no dia a dia real, avalia se vale a grana sem deslumbre de novidade.
Ver todos os artigos →