trilha

System Design/04 - Cloud Design Patterns/Messaging2 min

Async Request Reply

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

Conceito

O cliente faz uma requisição, o servidor aceita e responde imediatamente com um identificador; o resultado é obtido depois.

POST /relatorios      → 202 Accepted
                        Location: /jobs/abc123
GET  /jobs/abc123     → 200 { status: "processando", progresso: 40 }
                      → 200 { status: "pronto", url: "..." }

O 202 Accepted é a peça semântica: significa "recebi e vou processar", não "terminei".

Formas de entregar o resultado

Mecanismo Custo
Polling Simples; requisições desperdiçadas
Polling com backoff Bom equilíbrio — o padrão usual
Webhook Eficiente; exige o cliente ser alcançável
WebSocket / SSE Tempo real; conexão com estado

Detalhado em Returning Results.

Trade-offs

O ganho é desacoplar a duração do trabalho da duração da conexão. Sem isso, uma operação de cinco minutos exige manter uma conexão HTTP aberta por cinco minutos — atravessando timeouts de proxy, balanceador e cliente, e ocupando uma thread (Busy Frontend).

Os custos:

Mais estado. Alguém precisa guardar o status de cada job, por quanto tempo, e o que fazer com jobs que ninguém consulta.

Mais rodadas. Uma operação simples vira duas ou mais interações. Para trabalho de 200 ms, isso é pior que a chamada síncrona — o padrão só compensa quando a duração justifica.

Polling desperdiça. Intervalo de 1 s com job de 5 min são 300 requisições para uma resposta útil. Backoff progressivo (1 s, 2 s, 5 s, 10 s) é o meio-termo consagrado.

Webhook inverte a fragilidade: agora você depende de um endpoint alheio estar no ar, o que exige retry, assinatura e idempotência do outro lado.

E há uma decisão de desenho que evita problemas: o resultado grande não deve ir na resposta de status. O job grava no armazenamento e devolve uma URL (Claim Check com Valet Key).

Exemplo prático

Exportação de relatório.

POST /exportacoes        → 202 + { jobId: "abc" }
GET  /exportacoes/abc    → { status: "processando", progresso: 60 }
                         → { status: "pronto", url: "<assinada, 1 h>" }

O front faz polling com backoff e mostra a barra de progresso. Quando termina, o arquivo já está no armazenamento e a resposta traz apenas o link.

Isso mantém a API leve, tira o tráfego pesado dela, e o link expira sozinho. Se o usuário fechar a aba, o relatório continua sendo gerado — o desacoplamento entre execução e entrega é justamente o que torna isso possível.

Relacionado


Parte de Messaging · roadmap.sh/system-design

Buscar

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