7 padrões timeout falhas: evite cascata de erros
Timeouts mal configurados derrubam sistemas inteiros. Veja 7 padrões de timeout que evitam cascata de falhas e como aplicá-los na prática.
Timeouts mal configurados derrubam sistemas inteiros. Veja 7 padrões de timeout que evitam cascata de falhas e como aplicá-los na prática.
Quando um serviço demora, a espera não fica restrita a ele. Cada requisição pendurada ocupa thread, conexão e memória. Se o timeout não existe ou é longo demais, a lentidão vira epidemia: o serviço B espera o A, o C espera o B, e o sistema inteiro entra em colapso. Padrões de timeout bem definidos são a primeira linha de defesa contra cascata de falhas. Abaixo, os 7 mais eficazes, do mais básico ao mais estratégico.
1. Timeout fixo simples
É o padrão mais direto: define-se um limite absoluto de espera, por exemplo, 3 segundos para uma chamada HTTP. Se a resposta não chega, a requisição é cancelada e o erro é tratado. O valor precisa ser calibrado com base na latência normal do serviço chamado, não em um chute genérico.
Um critério prático: meça o percentil 99 da latência do serviço downstream em condições normais e adicione uma margem de 20% a 50%. Um timeout fixo mal calibrado, curto demais, gera falsos erros; longo demais, não protege nada.
2. Timeout por tipo de operação
Nem toda chamada merece o mesmo limite. Uma consulta de leitura pode responder em 200 ms, enquanto uma operação de escrita com processamento pesado leva 2 segundos. Aplicar um único timeout para tudo é receita para falhas desnecessárias.
Separe os timeouts por verbo HTTP ou por tipo de operação: leitura, escrita, autenticação, upload. Cada um com seu valor. Operações de escrita, por natureza, tendem a ser mais lentas e podem exigir limites maiores, desde que o downstream tenha capacidade real de responder.
3. Timeout progressivo (backoff)
Em vez de um valor fixo, o timeout cresce a cada tentativa. A primeira chamada espera 500 ms; se falha, a próxima espera 1 segundo; depois 2 segundos, até um teto máximo. Esse padrão é útil quando o serviço downstream está sobrecarregado e precisa de mais tempo para se recuperar.
O critério aqui é o número de tentativas: não repita indefinidamente. Defina um limite, normalmente 3 a 5 tentativas, e um teto para o backoff, por exemplo, 10 segundos. Sem teto, o padrão vira uma nova forma de cascata.
4. Timeout com jitter
Quando muitos clientes chamam o mesmo serviço com o mesmo timeout, eles tendem a falhar e repetir ao mesmo tempo. Isso cria picos sincronizados de requisições, exatamente o que derruba um sistema já fragilizado. O jitter resolve isso: adiciona uma variação aleatória ao timeout ou ao intervalo de retry.
Um exemplo concreto: em vez de repetir exatamente a cada 1 segundo, o cliente espera entre 800 ms e 1,2 segundos. A aleatoriedade espalha as requisições no tempo. É um padrão barato de implementar e com impacto grande na estabilidade.
5. Timeout baseado em latência histórica
Em vez de um valor estático, o timeout se ajusta dinamicamente com base no histórico de latência do serviço chamado. Se o percentil 95 das últimas respostas foi de 400 ms, o timeout pode ser definido em 600 ms. Se a latência média sobe, o timeout acompanha.
Esse padrão exige instrumentação: é preciso registrar e analisar as latências de cada chamada. Em troca, ele evita dois problemas comuns: timeouts curtos demais em serviços que naturalmente ficam mais lentos com o tempo, e timeouts longos demais que escondem degradação.
6. Timeout de leitura e escrita separados
Muitos clientes HTTP configuram um único timeout para a conexão inteira. Isso ignora que ler e escrever são fases diferentes. O timeout de conexão (estabelecer o socket) deve ser curto, geralmente abaixo de 1 segundo. O timeout de leitura (esperar o corpo da resposta) pode ser maior, pois depende do processamento do servidor.
Na prática, um timeout de conexão de 500 ms e um de leitura de 5 segundos são valores comuns em sistemas internos. Separar os dois evita que uma lentidão de rede seja confundida com lentidão do serviço, e dá diagnóstico mais preciso.
7. Timeout combinado com circuit breaker
Timeout sozinho protege o recurso local, mas não impede que o serviço downstream continue sendo bombardeado. O circuit breaker entra aqui: após um número de falhas em um intervalo, ele abre o circuito e bloqueia chamadas por um período, sem nem tentar.
Um exemplo de configuração: se 5 falhas por timeout ocorrerem em 10 segundos, o circuito abre por 30 segundos. Durante esse tempo, as chamadas falham rápido, sem consumir recursos. Combinar timeout com circuit breaker é o padrão mais completo desta lista, e o que melhor previne cascata em arquiteturas complexas.
Qual padrão escolher
Se você está começando, implemente o timeout fixo simples com valores calibrados por operação. É o mínimo aceitável. Se o sistema já apresenta falhas em horários de pico, adicione jitter nos retries e um circuit breaker no cliente. Padrões baseados em latência histórica e separação leitura/escrita são evoluções para quando você tem dados de telemetria suficientes. A ordem importa: comece pelo básico bem feito, em vez de pular direto para o sofisticado.
FAQ
Qual a diferença entre timeout e circuit breaker?
Timeout limita o tempo de espera de uma chamada individual. Circuit breaker bloqueia chamadas para um serviço inteiro quando ele está falhando repetidamente. Timeout protege o recurso local; circuit breaker protege o serviço downstream de receber mais carga do que aguenta.
Timeout curto demais pode causar problemas?
Sim. Se o timeout é menor que a latência normal do serviço, você gera falsos erros e retries desnecessários. Isso aumenta a carga no sistema em vez de reduzi-la. O valor precisa ser calibrado com base no percentil de latência real, não em intuição.
O que é cascata de falhas?
É quando a falha de um serviço se propaga para outros. Um serviço A espera uma resposta de B que nunca chega. As threads de A ficam ocupadas, novas requisições se acumulam, e A também para de responder. Sem timeouts, um único ponto lento derruba o sistema inteiro.
Devo usar o mesmo timeout para todos os serviços?
Não. Cada serviço downstream tem latências diferentes. Um banco de dados local responde em milissegundos; um gateway de pagamento pode levar segundos. Timeouts devem ser definidos por serviço e por tipo de operação, com base em medições reais.
Como calcular um bom valor de timeout?
Meça a latência do serviço em condições normais e use o percentil 99 como base. Adicione uma margem de 20% a 50% para variações. Monitore a taxa de erros por timeout e ajuste: se muitos erros, aumente; se o serviço degrada sem você perceber, diminua.
Jitter é obrigatório em todos os casos?
Não, mas é recomendado quando há muitos clientes chamando o mesmo serviço. Em arquiteturas com poucos consumidores, a sincronização de retries é menos provável. O jitter adiciona complexidade mínima e previne um problema que aparece justamente nos momentos de maior estresse.
Patrícia Lemos
Especialista em dados e analytics
Transforma painel cheio de número em decisão. Cuida de mensuração, dashboard e a métrica que de fato move o negócio.
Ver todos os artigos →