Estratégia antes da biblioteca

Defina o orçamento de latência da operação, quais erros são transitórios, se uma chamada pode ser repetida e qual resposta é segura quando a dependência falha. Timeout limita espera; retry tenta recuperar falhas transitórias; circuit breaker interrompe chamadas quando uma dependência segue indisponível. Nenhum deles substitui idempotência ou tratamento de negócio.

Para fundamentos e riscos, veja resiliência em sistemas distribuídos. Polly implementa mecanismos, não decide sozinho o comportamento correto para o produto.

Use o handler integrado ao HttpClientFactory

Para clientes HTTP em aplicações modernas .NET, o pacote Microsoft.Extensions.Http.Resilience oferece handlers padrão construídos sobre Polly. O handler agrupa estratégias como timeout, retry e circuit breaker, reduzindo configuração artesanal:

builder.Services
    .AddHttpClient("Catalogo", client =>
    {
        client.BaseAddress = new Uri("https://catalogo.interno/");
    })
    .AddStandardResilienceHandler();

Instale uma versão do pacote compatível com o runtime e consulte os defaults documentados para essa versão. Ajuste limites para a latência e capacidade reais da dependência; evite copiar os valores padrão como se fossem um SLO. Use o cliente nomeado ou tipado via IHttpClientFactory e não crie um HttpClient descartável por chamada.

Retry precisa considerar o efeito da operação

Retries são apropriados para falhas transitórias em operações repetíveis, mas uma resposta perdida não informa se o servidor já concluiu a ação. Repetir um POST que cria uma cobrança pode duplicar o efeito. Use idempotência na API remota ou uma chave de idempotência, limite tentativas e tempo total e considere backoff e jitter para evitar rajadas sincronizadas.

Não repita automaticamente erros de validação, autorização ou outros erros permanentes. Confirme quais métodos e respostas sua política cobre, inclusive quando a API remota retorna códigos de erro de negócio em uma resposta HTTP válida.

Timeouts e circuit breaker

Um timeout por tentativa e um prazo total da requisição respondem a perguntas diferentes. Se cada tentativa puder esperar demais, retries excedem o orçamento do chamador. Propague CancellationToken e mantenha os prazos das camadas alinhados.

O circuit breaker deixa de enviar chamadas por um período após falhas repetidas e testa a recuperação depois. Acompanhe transições e falhas rejeitadas; um circuito aberto deve ser visível nos logs e traces. Fallback só é adequado quando o resultado alternativo é seguro, como dados explicitamente defasados — nunca sucesso fictício.

Evite empilhar políticas

Se o handler, um SDK, o serviço de aplicação e um proxy repetirem a mesma chamada, o número total de tentativas pode crescer multiplicativamente. Escolha um lugar dono da política por fronteira, documente timeouts ponta a ponta e considere limites de concorrência. Um fallback em cache também precisa de TTL e indicação de atualidade.

Não registre tokens, payloads confidenciais ou respostas completas em callbacks de política. Registre nome da dependência, operação, tentativa, duração e resultado com cardinalidade controlada.

Teste e monitore o comportamento

Teste a política com handlers HTTP falsos: resposta transitória seguida de sucesso, falha permanente, timeout, cancelamento e circuito aberto. Verifique quantidade de chamadas e prazo total, não apenas se a requisição final passou. Em ambiente integrado, monitore latência, tentativas, falhas e chamadas rejeitadas.

Para correlacionar essas métricas com o restante da aplicação, veja OpenTelemetry, Serilog e Dynatrace. Para uma integração pública concreta, acompanhe o exemplo de dados do Banco Central em .NET.

Documentação e leituras relacionadas