Circuit Breaker: como parar uma falha antes que ela vire cascata
Um serviço lento em cascata derruba o sistema inteiro mais rápido que um serviço fora do ar. O circuit breaker existe pra isso: parar de tentar antes que a tentativa vire o problema.

Um serviço fora do ar é um problema conhecido: o chamador recebe erro, trata, segue a vida. Um serviço lento é pior — cada chamada trava uma thread ou conexão esperando um timeout que nunca chega rápido o bastante, e a fila de requisições represadas cresce até derrubar quem está chamando também. A consequência é direta: a falha deixa de ser local e vira cascata, subindo pela cadeia de serviços até derrubar partes do sistema que não tinham nada a ver com o problema original.
O circuit breaker (disjuntor, no sentido elétrico mesmo — o mesmo dispositivo que desarma antes de queimar a instalação) existe pra cortar essa cascata antes que ela se espalhe.
As três posições do disjuntor
O padrão funciona como uma máquina de estados com três posições:

- Fechado — estado normal. As chamadas passam direto pro serviço de destino, e o circuit breaker só conta falhas em segundo plano.
- Aberto — depois que as falhas ultrapassam um limite definido (ex.: 50% de erro numa janela de 10 segundos), o circuito abre. A partir daí, toda chamada nova falha na hora, sem nem tentar a rede — o chamador recebe erro imediato em vez de esperar um timeout.
- Meio-Aberto — depois de um tempo de espera configurado, o circuito deixa passar uma chamada de teste. Se ela funcionar, o circuito fecha de novo e o tráfego volta ao normal. Se falhar, reabre e o cronômetro de espera recomeça.
Na prática, isso significa que o serviço com problema ganha um período sem carga pra se recuperar — em vez de continuar recebendo o volume total de chamadas exatamente enquanto está mais fragilizado.
Por que não é só um try/catch com retry
Retry sozinho, sem circuit breaker, piora cascata: cada chamada que falha e tenta de novo multiplica a carga sobre um serviço que já está com dificuldade de responder. É o oposto do efeito desejado — mais tentativa, mais pressão, mais lentidão, ciclo que se retroalimenta.
O circuit breaker resolve isso interrompendo a tentativa completamente durante o estado aberto. Ou seja: retry ajuda a resolver falha transitória pontual; circuit breaker protege o sistema inteiro de uma falha persistente que retry sozinho só pioraria.
Onde isso costuma dar errado
- Limiar mal calibrado — threshold de erro baixo demais abre o circuito por qualquer soluço passageiro; alto demais deixa a cascata se formar antes de agir
- Tempo de espera fixo demais — não se adapta a serviços com padrões de recuperação diferentes; um serviço de banco de dados e uma API de terceiro não se recuperam no mesmo ritmo
- Fallback ausente — abrir o circuito sem ter uma resposta alternativa (cache, valor default, degradação graciosa) só transforma "erro lento" em "erro rápido", sem resolver a experiência de quem está do outro lado
Nenhum desses três é motivo pra não usar o padrão — são motivo pra calibrar com dado real de produção em vez de valor padrão de biblioteca, e pra sempre desenhar o fallback junto com o disjuntor, não depois.