trilha

System Design/02 - Componentes/Asynchronism2 min

Back Pressure

Perguntas-guia
  • Que problema isso resolve?
  • Quando usar / quando NÃO usar?
  • Qual o principal trade-off?
  • Como isso falha em produção?

Conceito

Back pressure é o mecanismo pelo qual um componente sobrecarregado sinaliza para trás que não consegue absorver mais trabalho — fazendo o produtor desacelerar em vez de continuar empurrando.

Sem ele, o excesso vira fila crescente, memória consumida e, por fim, colapso.

Por que a fila não resolve sozinha

Uma fila absorve pico — variação temporária. Se a taxa média de chegada excede a de processamento, a fila cresce indefinidamente:

chegada 1.000/s, processamento 800/s
→ +200 mensagens/s acumuladas
→ em 1 hora: 720.000 mensagens presas
→ latência da última mensagem: ~15 minutos

O sistema parece "no ar" enquanto entrega respostas cada vez mais velhas — modo de falha pior do que rejeitar.

Mecanismos

Mecanismo Como funciona
Fila limitada Ao encher, bloqueia ou rejeita o produtor
Throttling / rate limit Rejeita com 429 Too Many Requests
Load shedding Descarta o trabalho de menor valor deliberadamente
Pull em vez de push O consumidor puxa no seu ritmo (Kafka, Reactive Streams)
Semáforo Limita concorrência (Bulkhead)
Timeout agressivo Abandona trabalho que já não interessa a ninguém

Trade-offs

Back pressure exige rejeitar trabalho — e isso parece errado até você ver a alternativa. A escolha real não é "aceitar tudo ou rejeitar alguns"; é "rejeitar alguns explicitamente" ou "degradar para todos e cair".

Rejeitar cedo e rápido (429) é quase sempre melhor que aceitar e demorar: o cliente pode tentar outro caminho, e o sistema não gasta recursos em trabalho que vai expirar.

O risco de propagar back pressure é a paralisia em cascata: se A desacelera porque B desacelerou, e o cliente de A é o usuário, o usuário sente. Por isso costuma vir combinado com load shedding — em vez de desacelerar todos, sacrifica-se o tráfego menos importante.

Fila ilimitada é sempre um bug, mesmo quando parece generosidade: transforma um problema de capacidade visível num problema de memória invisível.

Exemplo prático

Um serviço de ingestão recebe eventos e grava num banco que aguenta 5.000 escritas/s. Chegam 8.000/s.

Sem back pressure: buffer em memória cresce, GC sofre, latência sobe, e o processo morre por OOM — perdendo tudo que estava em memória.

Com back pressure: o buffer é limitado a 10.000. Ao encher, o serviço responde 429 com Retry-After. O cliente reduz o ritmo. O sistema entrega 5.000/s de forma estável e rejeita o excesso previsivelmente — e a métrica de rejeição torna o déficit de capacidade visível antes de virar incidente.

Relacionado


Parte de Asynchronism · roadmap.sh/system-design

Buscar

Busca por título, seção e texto das notas