Como usar Polly para retry e circuit breaker ao consultar CPF em .NET

Implemente retry e circuit breaker com Polly ao consultar a API de CPF em .NET para maior resiliência e disponibilidade.

Redação CPFHub.io
Redação CPFHub.io
··5 min de leitura
Como usar Polly para retry e circuit breaker ao consultar CPF em .NET

O Polly é a biblioteca de resiliência padrão para .NET que permite implementar retry com backoff exponencial e circuit breaker em chamadas à API de CPF, garantindo que falhas temporárias de rede não interrompam o fluxo de validação e que o sistema se recupere automaticamente sem intervenção manual.

Introdução

Ao consumir APIs externas como a do CPFHub.io, falhas temporárias de rede, timeouts e sobrecarga do servidor são situações inevitáveis. O Polly é uma biblioteca de resiliência para .NET que permite implementar padrões como retry com backoff exponencial e circuit breaker.


Instalando e configurando o Polly

Adicione o pacote Polly ao seu projeto junto com a extensão para IHttpClientFactory:

dotnet add package Microsoft.Extensions.Http.Polly
dotnet add package Polly.Extensions.Http

O Polly se integra nativamente ao IHttpClientFactory do ASP.NET Core, permitindo aplicar políticas de resiliência diretamente na configuração do HttpClient.


Implementando retry com backoff exponencial

O retry com backoff exponencial aguarda intervalos crescentes entre tentativas, reduzindo a carga no servidor durante instabilidades.

using Polly;
using Polly.Extensions.Http;

public static class PollyPolicies
{
    public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
    return HttpPolicyExtensions
    .HandleTransientHttpError()
    .WaitAndRetryAsync(
    retryCount: 3,
    sleepDurationProvider: tentativa =>
    TimeSpan.FromSeconds(Math.Pow(2, tentativa)),
    onRetry: (outcome, timespan, tentativa, context) =>
    {
    Console.WriteLine(
    $"Tentativa {tentativa} após {timespan.TotalSeconds}s. " +
    $"Status: {outcome.Result?.StatusCode}");
    });
    }
}
TentativaIntervaloTempo Total Acumulado
1a2 segundos2s
2a4 segundos6s
3a8 segundos14s

Implementando circuit breaker

O circuit breaker interrompe chamadas à API quando detecta muitas falhas consecutivas, evitando sobrecarregar um serviço já instável.

public static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
    .HandleTransientHttpError()
    .CircuitBreakerAsync(
    handledEventsAllowedBeforeBreaking: 5,
    durationOfBreak: TimeSpan.FromSeconds(30),
    onBreak: (outcome, breakDelay) =>
    {
    Console.WriteLine(
    $"Circuit aberto por {breakDelay.TotalSeconds}s. " +
    $"Razão: {outcome.Exception?.Message ?? outcome.Result?.StatusCode.ToString()}");
    },
    onReset: () =>
    {
    Console.WriteLine("Circuit fechado. Retomando chamadas normalmente.");
    },
    onHalfOpen: () =>
    {
    Console.WriteLine("Circuit semi-aberto. Testando próxima chamada.");
    });
}

Combinando políticas com PolicyWrap

O verdadeiro poder do Polly está em combinar múltiplas políticas. Aplique retry dentro do circuit breaker para máxima resiliência.

public static IAsyncPolicy<HttpResponseMessage> GetResiliencePolicy()
{
    var retryPolicy = GetRetryPolicy();
    var circuitBreakerPolicy = GetCircuitBreakerPolicy();

    return Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);
}

Registre a política combinada no Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpClient<ICpfApiClient, CpfApiClient>(client =>
{
    client.BaseAddress = new Uri("https://api.cpfhub.io/");
    client.DefaultRequestHeaders.Add("x-api-key",
    builder.Configuration["CpfHub:ApiKey"]);
    client.Timeout = TimeSpan.FromSeconds(10);
})
.AddPolicyHandler(PollyPolicies.GetResiliencePolicy());

builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

Tratando o estado do circuit breaker

Quando o circuit breaker está aberto, é importante informar o usuário de forma adequada em vez de simplesmente falhar.

[ApiController]
[Route("api/[controller]")]
public class CpfController : ControllerBase
{
    private readonly ICpfApiClient _cpfClient;

    public CpfController(ICpfApiClient cpfClient)
    {
    _cpfClient = cpfClient;
    }

    [HttpGet("{cpf}")]
    public async Task<IActionResult> Consultar(string cpf)
    {
    try
    {
    var resultado = await _cpfClient.ConsultarAsync(cpf);

    if (resultado is { Success: true })
    return Ok(resultado.Data);

    return NotFound(new { message = "CPF não encontrado" });
    }
    catch (Polly.CircuitBreaker.BrokenCircuitException)
    {
    return StatusCode(503, new
    {
    message = "Serviço temporariamente indisponível. Tente novamente em breve.",
    retryAfter = 30
    });
    }
    catch (Exception)
    {
    return StatusCode(502, new
    {
    message = "Erro ao consultar o serviço de CPF"
    });
    }
    }
}

Perguntas frequentes

Por que usar backoff exponencial em vez de intervalos fixos entre tentativas?

O backoff exponencial evita o efeito de "thundering herd": quando muitos clientes reagem a uma falha ao mesmo tempo com intervalos fixos, todos retentam juntos e ampliam a sobrecarga. Com intervalos crescentes (2s, 4s, 8s), o tráfego se distribui naturalmente e o serviço recupera com mais facilidade.

Quando o circuit breaker deve ser usado junto com o retry?

Sempre que a API externa puder ficar indisponível por períodos prolongados. O retry lida com falhas transitórias curtas; o circuit breaker interrompe as tentativas quando o serviço está claramente fora do ar, poupando recursos e retornando respostas de fallback rapidamente ao invés de aguardar timeouts sucessivos.

Como monitorar o estado do circuit breaker em produção?

Registre os eventos onBreak, onReset e onHalfOpen em um sistema de observabilidade como Application Insights, OpenTelemetry ou Serilog. A documentação oficial do Polly recomenda expor o estado atual como métrica para alertas automáticos quando o circuit abrir com frequência.

A CPFHub.io bloqueia requisições quando o limite do plano é atingido?

Não. A CPFHub.io nunca retorna 429 nem bloqueia consultas ao atingir o limite mensal. O plano gratuito inclui 50 consultas/mês e, a partir da 51ª, cada consulta é cobrada a R$0,15. O plano Pro oferece 1.000 consultas por R$149/mês com o mesmo modelo de excedente.


Conclusão

Implementar retry e circuit breaker com Polly é essencial para qualquer aplicação .NET que dependa de APIs externas. Essas políticas de resiliência garantem que falhas temporárias não comprometam a experiência do usuário e que o sistema se recupere automaticamente.

Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a integrar a consulta de CPF com resiliência total na sua aplicação .NET.

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

Sobre a redação

Redação CPFHub.io

Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.

WhatsAppFale conosco via WhatsApp