System Design/02 - Componentes/Asynchronism2 min
Task Queues
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Uma fila com semântica de trabalho: além de transportar, ela sabe reexecutar, agendar, priorizar e reportar resultado.
| Message Queues | Task Queue | |
|---|---|---|
| Transporta | Mensagem genérica | Tarefa (função + argumentos) |
| Retry | Você implementa | Embutido, com backoff |
| Agendamento | Não | Sim (executar em 1 h) |
| Resultado | Você resolve | Backend de resultado |
| Exemplos | RabbitMQ, SQS, Kafka | Celery, Sidekiq, BullMQ |
Na prática a task queue usa uma message queue por baixo e adiciona a camada de orquestração de trabalho: retry com backoff, agendamento tipo cron, prioridade entre filas (Priority Queue), encadeamento de pipelines, e um painel de filas e falhas.
Trade-offs
Passar objetos complexos como argumento parece natural e é armadilha: os argumentos são serializados, e um objeto que existia no enfileiramento pode não existir mais na execução. A prática correta é passar IDs, não objetos — e recarregar do banco dentro da tarefa.
Retry automático é útil e perigoso: sem idempotência, ele duplica efeito colateral. Uma tarefa que envia e-mail e falha ao gravar no banco reenvia o e-mail a cada tentativa.
Retry também precisa distinguir erro transitório (rede, timeout — vale repetir) de permanente (dado inválido — repetir só desperdiça). Sem essa distinção, uma tarefa venenosa consome o pool de workers indefinidamente. E retry em massa cria Retry Storm.
O backend de resultado é frequentemente esquecido: guardar retorno de milhões de tarefas em Redis, sem TTL, é forma comum de estourar memória em produção.
Exemplo prático
Um relatório mensal agendado para 3h da manhã:
tarefa: gerar_relatorio(cliente_id, mes)
retry: 3 tentativas, backoff 60s → 120s → 240s
fila: 'relatorios' (prioridade baixa)
timeout: 30 min
Note o que está declarado: a tarefa recebe IDs, não o objeto cliente. Vive numa fila de baixa prioridade para não competir com tarefas interativas. Tem timeout, porque tarefa sem timeout trava o worker para sempre. E tem retry limitado, porque tentar infinitamente um relatório impossível é pior que falhar e alertar.
Relacionado
Parte de Asynchronism · roadmap.sh/system-design