System Design/05 - Reliability Patterns/Resiliency2 min
Bulkhead
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Isolar recursos em compartimentos, para que a falha de um não afunde o sistema inteiro. O nome vem das antéparas de um navio: um compartimento inundado não alaga os demais.
sem bulkhead: [ pool único de 100 conexões ]
serviço A lento → consome as 100 → B e C morrem
com bulkhead: [ A: 40 ] [ B: 40 ] [ C: 20 ]
A lento → consome só as 40 dele
Onde aplicar
| Nível | Compartimento |
|---|---|
| Pool de conexões | Por dependência |
| Pool de threads | Por tipo de operação |
| Semáforo | Limite de concorrência por dependência |
| Instâncias | Separar crítico de não-crítico |
| Clientes | Deployment Stamps |
Trade-offs
O ganho é conter o dano: uma dependência lenta deixa de derrubar tudo. É a defesa estrutural contra Noisy Neighbor e contra a exaustão de pool descrita em Busy Frontend.
O custo é eficiência. Recursos compartimentados ficam ociosos enquanto outro compartimento sofre: com 40 conexões reservadas para A e A ocioso, B não pode usá-las mesmo precisando. Isolamento garante o mínimo e sacrifica o pico.
Isso torna o dimensionamento delicado: compartimentos pequenos demais viram gargalo em uso legítimo; grandes demais não isolam nada. E dividir um pool de 100 em dez de dez costuma ser pior que não dividir.
A implementação por semáforo é a mais leve — limita concorrência sem threads dedicadas — e não isola tempo de CPU. A implementação por pool de threads isola de verdade e custa memória por thread.
Bulkhead combina com Circuit Breaker de forma complementar: o bulkhead limita quanto uma dependência pode consumir; o breaker decide quando parar de tentar. Um contém, o outro interrompe.
Exemplo prático
Uma API que depende de três serviços: pagamento (crítico), recomendação e analytics (ambos opcionais).
Com pool único de 100 conexões, analytics fica lento e consome todas — e o pagamento para de funcionar por causa de um serviço que não importa.
Com bulkhead:
pagamento: 60 conexões, timeout 3 s
recomendacao: 25 conexões, timeout 1 s, fallback em cache
analytics: 15 conexões, timeout 500 ms, fire-and-forget
Analytics lento consome no máximo suas 15 conexões. Pagamento continua com as 60 dele. A alocação reflete a criticidade — e é essa decisão explícita que o padrão exige e entrega.
Relacionado
Parte de Resiliency · roadmap.sh/system-design