System Design/05 - Reliability Patterns/Resiliency2 min
Circuit Breaker
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Interrompe chamadas a uma dependência que está claramente falhando, evitando desperdiçar recursos e dar tempo de ela se recuperar. O nome vem do disjuntor elétrico.
Os três estados
FECHADO ──falhas > limiar──→ ABERTO
↑ │
│ após timeout
sucesso ↓
└──────────────────── MEIO-ABERTO
(deixa passar 1 chamada de teste)
| Estado | Comportamento |
|---|---|
| Fechado | Tudo passa; conta as falhas |
| Aberto | Falha imediatamente, sem tentar |
| Meio-aberto | Deixa passar uma chamada; sucesso fecha, falha reabre |
Trade-offs
O ganho principal é falhar rápido. Sem o breaker, cada chamada a um serviço morto consome uma thread pelo tempo do timeout — e, com tráfego suficiente, o pool esgota e o serviço chamador cai junto. O breaker converte espera em erro imediato, preservando os recursos.
O ganho secundário é dar espaço para a recuperação: um serviço sobrecarregado que para de receber tráfego consegue drenar sua fila. Continuar batendo nele impede que ele se levante.
Os custos e riscos:
Calibração. Limiar muito sensível abre o circuito em falhas normais e derruba a disponibilidade sem necessidade; muito tolerante não protege. Limiar por percentual de falhas (com volume mínimo) é mais robusto que contagem absoluta.
Rejeição em massa. Com o circuito aberto, todas as requisições falham — inclusive as que teriam sucesso. Por isso o padrão pede um fallback: cache, valor padrão, resposta degradada. Sem fallback, o breaker apenas troca lentidão por erro.
Granularidade. Um breaker por dependência é o mínimo; por endpoint é melhor, porque um endpoint quebrado não deveria bloquear os demais do mesmo serviço.
E vale a combinação natural: breaker por fora, Retry por dentro, Bulkhead limitando a concorrência — cada um tratando um aspecto distinto do problema.
Exemplo prático
Um serviço de recomendação fica fora. Sem breaker, com timeout de 5 s:
100 req/s × 5 s de espera = 500 threads presas
→ o pool esgota → a página inteira para de responder
Uma dependência não crítica derrubou o site.
Com breaker: após 20 falhas consecutivas, o circuito abre. As chamadas seguintes falham em microssegundos e o código cai no fallback — recomendações genéricas em cache.
A página continua carregando normalmente; apenas o bloco de recomendações fica menos personalizado. E, a cada 30 segundos, uma chamada de teste verifica se o serviço voltou.
Relacionado
Parte de Resiliency · roadmap.sh/system-design