System Design/03 - Qualidade/Performance Antipatterns2 min
Noisy Neighbor
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Um consumidor monopoliza um recurso compartilhado e degrada todos os demais. É um problema de isolamento ausente, não de capacidade.
Onde acontece
| Recurso compartilhado | Como o vizinho barulhento aparece |
|---|---|
| Banco multi-tenant | Um cliente roda consulta que varre tudo |
| Pool de conexões | Um endpoint lento consome todas as conexões |
| Pool de threads | Uma operação bloqueante ocupa o pool (Busy Frontend) |
| Cluster de cache | Uma hot key satura um nó |
| Fila compartilhada | Um produtor inunda e atrasa os outros |
| Host físico | Outra VM consome I/O |
| Partição | Sharding com distribuição desigual |
As defesas
| Defesa | Como funciona |
|---|---|
| Bulkhead | Pools separados por consumidor ou por dependência |
| Throttling / cota | Limite por tenant, por plano |
| Prioridade | Priority Queue — trabalho crítico não espera |
| Isolamento físico | Tenant grande ganha recurso dedicado |
| Deployment Stamps | Grupos de tenants em instâncias separadas |
| Timeout | Limita quanto tempo alguém pode ocupar o recurso |
Trade-offs
Isolamento e eficiência são opostos diretos. Recursos compartilhados têm alta utilização e sofrem interferência; recursos dedicados são previsíveis e ficam ociosos.
A escala do trade-off é econômica: dar um banco dedicado a cada tenant elimina o problema e multiplica o custo por N. Por isso a estratégia usual é híbrida — a maioria dos tenants em infraestrutura compartilhada, e os poucos que sozinhos causam impacto promovidos a recursos dedicados.
Cotas resolvem bem o caso previsível e não resolvem o caso patológico: uma única consulta mal escrita pode consumir mais que a cota horária inteira em segundos. Aí o que protege é timeout e limite de recurso por consulta, não cota agregada.
E há o efeito perverso de bulkhead mal dimensionado: dividir 100 conexões em dez pools de dez significa que um consumidor com pico legítimo fica limitado a dez, mesmo com 90 conexões ociosas. Isolamento garante o mínimo e sacrifica o burst.
Exemplo prático
Um SaaS com 500 clientes no mesmo banco. Um deles roda um relatório que varre 40 milhões de linhas, e todos os 500 ficam lentos por dez minutos.
As camadas de correção, em ordem de custo:
1. timeout por consulta (30 s) → limita o dano de qualquer consulta
2. pool separado para relatórios → relatório não consome conexões do tráfego
3. réplica de leitura para análise → varredura sai do primário
4. shard dedicado para o cliente → só se ele sozinho justificar
As três primeiras não exigem infraestrutura nova e resolvem quase todos os casos. A quarta é a única que escala em custo com o número de clientes problemáticos — e por isso fica por último.
Relacionado
Parte de Performance Antipatterns · roadmap.sh/system-design