System Design/02 - Componentes/Background Jobs2 min
Returning Results
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Quando o trabalho vira assíncrono, a resposta imediata deixa de conter o resultado. O sistema precisa de um caminho de volta.
O padrão base é Async Request Reply: a API aceita, devolve 202 Accepted com um identificador, e o cliente descobre o desfecho depois.
POST /videos → 202 Accepted
Location: /jobs/abc123
GET /jobs/abc123 → 200 { status: "processando" }
→ 200 { status: "pronto", url: "..." }
As quatro formas de devolver
| Mecanismo | Como funciona | Custo |
|---|---|---|
| Polling | Cliente consulta o status periodicamente | Simples; requisições desperdiçadas |
| Long polling | Servidor segura a conexão até haver resposta | Menos desperdício; conexões ocupadas |
| Webhook | Servidor chama uma URL do cliente | Eficiente; exige o cliente ser alcançável |
| WebSocket / SSE | Canal aberto, push em tempo real | Melhor UX; conexão com estado, escala pior |
Onde o resultado fica
Um result store (Redis, banco, S3) guarda o desfecho por um tempo. Três decisões: quanto tempo reter, o que fazer se o cliente nunca buscar, e se o resultado é o dado ou apenas um link para ele (resultados grandes devem ir para armazenamento e o job devolver a URL — é o Claim Check).
Trade-offs
Polling é o mais simples e o mais desperdiçador: com intervalo de 1 s e job de 5 min, são 300 requisições para uma resposta útil. Aumentar o intervalo reduz custo e piora a percepção de rapidez. Backoff progressivo (1 s, 2 s, 5 s, 10 s) é o meio-termo usual.
Webhook inverte a responsabilidade: agora você é cliente de um endpoint que pode estar fora do ar, ser lento ou responder erro. Exige retry com backoff, assinatura para autenticidade, e idempotência do lado de quem recebe — porque o webhook vai ser entregue duas vezes eventualmente.
WebSocket dá a melhor experiência e transforma um serviço stateless em stateful: a conexão pertence a uma instância específica, o que complica deploy, balanceamento e escala.
Exemplo prático
Exportação de relatório grande. O usuário clica, a API responde 202 com jobId e a interface mostra uma barra de progresso.
O front faz polling com backoff. Quando o job termina, o resultado não vai na resposta — o worker grava o arquivo no armazenamento de objetos e devolve uma URL assinada com expiração. A API responde { status: "pronto", url: "..." }.
Isso mantém a resposta pequena, tira o tráfego pesado da API e faz o link expirar sozinho. Se o usuário fechar a aba, o relatório continua lá — o desacoplamento entre execução e entrega é o que torna isso possível.
Relacionado
Parte de Background Jobs · roadmap.sh/system-design