System Design/04 - Cloud Design Patterns/Messaging2 min
Async Request Reply
- 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