O circuit breaker que mente para você sobre resiliência
Mostra por que a explicação de manual do padrão circuit breaker não basta em produção: calibrar os limites de falha, desenhar o estado half-open, decidir o que acontece com as requests rejeitadas e evitar que o breaker vire um ponto cego sem observabilidade de verdade.

São 2h47 da manhã e o PagerDuty acabou de te acordar. O checkout está devolvendo 503, a latência do serviço de pagamentos vem subindo há quinze minutos e alguém no canal do incidente escreve: “o circuit breaker deveria estar segurando isso”. Você abre o dashboard. O breaker abriu, sim. O que você não consegue saber é quantas requests ele está descartando em silêncio agora, se o limite que o fez abrir foi calibrado algum dia para esse padrão de tráfego, ou quando ele vai tentar fechar de novo. Se essa cena parece familiar, você já sabe do que este artigo trata de verdade: não do que é um circuit breaker, e sim de tudo o que a explicação de manual pula sem avisar.
A definição rápida você já conhece. Um circuit breaker corta as chamadas para uma dependência que está falhando, para que essa falha não se espalhe pelo resto do sistema. Isso é verdade, e está longe de ser a história completa. Configurar um circuit breaker com uma biblioteca pronta leva quinze minutos. Fazer esse circuit breaker tomar boas decisões em produção, sob carga real, com dados reais, é um problema de engenharia sério, que a maioria das equipes resolve pela metade no primeiro dia e nunca mais revisita.
O que o padrão circuit breaker te dá de fato, e o que não dá
O circuit breaker resolve um problema específico e real: impede que uma dependência lenta ou fora do ar consuma todas as threads, conexões ou recursos do lado de quem chama, e impede que esse esgotamento suba pela cadeia de dependências. Quem já viu uma única query lenta no banco derrubar um API gateway inteiro entende exatamente por que esse padrão existe.
O que ele não resolve é a pergunta sobre o que vem depois. Um circuit breaker não conserta a dependência que está falhando, não decide o que o usuário vê, não te diz se a falha é passageira ou estrutural, e não substitui uma estratégia de degradação real. É uma válvula, não uma solução. E, como toda válvula, o valor dela depende inteiramente de como você a calibra. É exatamente aí que a maioria das implementações de circuit breaker desmorona: elas entram como um item de checklist de boas práticas e depois ninguém mexe nelas de novo.
Calibrar os limites de falha é a parte que ninguém explica direito
Todo tutorial mostra o mesmo exemplo de brinquedo: se a taxa de erro passar de 50% numa janela de 10 segundos, abra o circuito. Fica bonito num slide. Em produção, vira uma bagunça de decisões que ninguém se dá ao trabalho de documentar.
Esses 50% são medidos sobre 10 requests ou sobre 10.000? Porque, com pouco tráfego, um punhado de erros abre o breaker por puro ruído estatístico, e agora você está cortando uma dependência que, na prática, está saudável. A janela é fixa ou deslizante? Timeouts contam igual a erros 500, ou um timeout de 30 segundos pesa diferente de uma rejeição instantânea? O limite que faz sentido numa terça-feira tranquila à tarde continua certo durante um pico de tráfego dez vezes maior que o normal?
A resposta certa quase nunca é um número padrão copiado do README da sua biblioteca favorita. Ela sai da distribuição real de latência e de erros daquela dependência específica, naquelas condições específicas, e precisa ser revista toda vez que o padrão de tráfego muda de forma relevante. Um circuit breaker calibrado uma vez no lançamento e nunca mais tocado é, na melhor das hipóteses, um placebo. Na pior, ele começa a abrir por ruído e cria exatamente a instabilidade que deveria evitar.
O estado half-open é onde mora a ambiguidade real
Dos três estados de um circuit breaker (closed, open, half-open), os dois primeiros são fáceis de entender. O terceiro é onde você descobre se a sua implementação é séria ou de brinquedo.
O half-open existe para responder uma pergunta incômoda: a dependência que falhou se recuperou mesmo? A resposta ingênua é deixar passar uma request de teste e, se ela der certo, fechar o circuito de uma vez. O problema é que uma request bem-sucedida não diz nada sobre a dependência aguentar o volume total de tráfego que você vai mandar para ela no instante em que fechar. É comum ver breakers que fecham, recebem todo o tráfego acumulado de uma vez, assistem à dependência mal recuperada cair de novo com esse pico, e abrem outra vez. Esse ciclo pode se repetir indefinidamente, e quase ninguém o diagnostica como um problema do breaker. A leitura costuma ser “o serviço downstream continua com problema”.
As implementações que se sustentam em produção usam o half-open para aumentar o tráfego aos poucos, e não como um interruptor binário: deixe passar uma porcentagem pequena primeiro e só aumente se a dependência continuar saudável por um tempo razoável. Também vale decidir explicitamente quanto tempo o breaker espera antes de tentar o half-open, e esse número também não deveria ser um padrão mágico. Curto demais, e você cai no ciclo de abre e fecha sem parar. Longo demais, e você mantém uma dependência perfeitamente saudável isolada sem necessidade, enquanto o resto do sistema roda em modo degradado sem motivo.
O que acontece com as requests descartadas enquanto o circuito está aberto
Essa é a pergunta que quase nenhuma equipe responde antes de ela aparecer em produção pela primeira vez. O breaker abriu. Ótimo, ele impediu que a falha se espalhasse. E agora, o que você devolve para quem fez a chamada?
As opções reais são poucas, e todas têm um custo. Você pode falhar rápido com um erro explícito, o que é honesto, mas só empurra o problema para cima na cadeia: agora quem chamou precisa decidir o que fazer com esse erro. Você pode devolver uma resposta em cache ou um valor padrão razoável, o que funciona bem para um catálogo de produtos ou um widget de recomendações, e é francamente perigoso para qualquer coisa que envolva estoque, saldo ou autorização de pagamento. Você pode colocar a request numa fila para tentar de novo depois, o que só faz sentido se a operação tolera ser assíncrona e ninguém está olhando para um spinner esperando por ela.
Não existe resposta universal, e esse é justamente o ponto: cada dependência que você envolve num circuit breaker precisa de uma decisão de fallback explícita e documentada, tomada por alguém que entende a lógica de negócio por trás daquela chamada. Copiar a mesma estratégia de fallback para dez serviços sem relação entre si porque “é assim no exemplo do framework” é uma das formas mais comuns de um circuit breaker virar, sem ninguém perceber, uma fonte de bugs silenciosos.
Um circuit breaker sem observabilidade é pior do que nenhum circuit breaker
Aqui está a parte incômoda deste artigo. Um circuit breaker que abre e fecha sem ninguém olhar, sem uma métrica de quantas vezes ele muda de estado, sem um alerta quando ele fica aberto mais tempo que o esperado, sem visibilidade de quanto tráfego está sendo descartado enquanto ele está aberto, não está te protegendo. Ele está mentindo para você.
A equipe que colocou o breaker em produção dorme tranquila, achando que a resiliência está resolvida. Enquanto isso, o breaker pode estar abrindo cinco vezes por hora por causa de um limite mal calibrado, descartando em silêncio uma fatia real do tráfego de usuários, e ninguém percebe até alguém do suporte perguntar por que as conversões caíram 8% na semana passada. Um sistema sem circuit breaker pelo menos falha fazendo barulho: o erro aparece, alguém vê, alguém reage. Um circuit breaker mal observado transforma essa falha barulhenta e visível numa falha silenciosa, e em qualquer sistema em produção, falha silenciosa é estritamente pior do que falha barulhenta.
O mínimo inegociável é expor o estado atual de cada breaker como métrica, contar as transições de estado, medir o volume de requests rejeitadas enquanto ele está aberto e ter um alerta que dispara quando um breaker fica aberto mais tempo que o esperado. Sem essa instrumentação, o circuit breaker deixa de ser uma ferramenta de resiliência e vira mais um ponto único de falha, invisível justamente porque ninguém está olhando para ele.
O que importa de verdade
Um circuit breaker bem calibrado, com um estado half-open desenhado com cuidado, estratégias de fallback explícitas para cada dependência e observabilidade de verdade, é uma das peças mais valiosas que você pode ter num sistema distribuído. Mas essa combinação é rara. O comum é uma biblioteca instalada com as configurações padrão, um limite que ninguém olhou desde o dia do lançamento e zero alertas se algo der errado.
Esta é a nossa posição, sem rodeios, e não é a que você vai encontrar na documentação da biblioteca: um circuit breaker sem métricas e alertas reais é, na prática, pior do que não ter nenhum. Sem observabilidade, um circuit breaker não te dá resiliência, te dá a ilusão de resiliência, o que é muito mais perigoso, porque te convence a parar de prestar atenção exatamente onde você mais precisa. Se você vai colocar um em produção, a pergunta que define se ele vale alguma coisa não é “qual biblioteca devo usar”. É “quem fica sabendo, e com que rapidez, quando esse breaker começa a se comportar mal”. Se você não tem uma resposta clara para isso, você ainda não tem um circuit breaker. Você tem a promessa de um.
ESCRITO POR
Explore mais novidades
Ver mais
Agentes de IA para programar não são assistentes. Veja o que muda de verdade quando você faz a troca

Por que engenheiros sênior estão apostando em agentes de código aberto em vez de ficar presos a um fornecedor
