3 de Junho de 2025
Jobs Assíncronos, Filas e Workers: o Fluxo Completo
Como pensar do request inicial até o resultado final quando o trabalho sai da request web e vai para fila, retry e processamento em background.
Andrews Ribeiro
Founder & Engineer
4 min Intermediario Sistemas
O problema
Tem trabalho que simplesmente não cabe bem dentro da request web.
Exemplos comuns:
- gerar relatório
- processar video
- enviar lote de emails
- importar arquivo grande
Quando o time tenta resolver tudo dentro do request, aparecem sintomas previsiveis:
- timeout
- usuário esperando demais
- queda de throughput
- falha parcial difícil de entender
A reação tipica e:
“Joga na fila.”
Só que esse conselho sozinho ainda e raso.
Porque fila não resolve o sistema inteiro. Ela resolve só uma parte.
Modelo mental
Pense em job assíncrono como um fluxo com cinco momentos:
- A aplicação aceita a intenção.
- O estado inicial do job fica persistido.
- O trabalho entra numa fila.
- Um worker processa com retry e idempotencia.
- O resultado ou falha fica visível para alguém.
Se qualquer uma dessas partes fica fraca, o sistema vira uma maquina de “não sei onde isso travou”.
Quebrando o problema
A request não entrega resultado. Ela entrega aceite
Em muito caso assíncrono, a resposta certa para o cliente não e “pronto”.
E algo mais honesto:
- “aceitei seu pedido”
- “seu job foi criado”
- “acompanhe por este id”
Isso costuma virar um 202 Accepted ou um 200 com semântica explicita de processamento pendente.
O estado do job precisa existir fora da fila
Esse ponto e crucial.
Se você só publica uma mensagem e não registra estado, depois fica ruim responder perguntas basicas:
- esse job existe?
- esta pendente?
- esta processando?
- falhou?
- terminou?
Por isso muita arquitetura cria um registro do job antes:
queuedprocessingcompletedfailed
Fila sem estado de negócio costuma deixar rastreabilidade fraca.
Enfileirar com segurança importa
Aqui mora uma falha classica:
- salva no banco, mas não publica na fila
- publica na fila, mas não salva no banco
Os dois deixam o sistema incoerente.
Dependendo do caso, você precisa de estratégia para reduzir essa janela, como:
- transação bem desenhada
- outbox pattern
- reconciliação operacional
O ponto não e decorar nome bonito.
E evitar que a intenção se perca no meio.
Worker não e script solto
O worker precisa fazer mais do que “ler mensagem e rodar função”.
Ele normalmente precisa:
- buscar ou validar o job
- marcar como
processing - executar a tarefa
- persistir resultado
- confirmar consumo
- reagir a falha
E como mensagem pode repetir, o worker precisa aguentar reprocessamento sem estrago.
Se ele chama serviço externo, grava arquivo ou muda estado de negócio, essa repetição precisa ser pensada antes.
Retry sem critério piora tudo
Nem toda falha merece retry igual.
Falha transitoria pode pedir:
- retry
- backoff
- limite de tentativas
Falha permanente pode pedir:
- marcar como failed
- mandar para DLQ
- abrir caminho de inspeção manual
Retry infinito em erro permanente só move o problema de lugar.
E polling sem contrato claro também.
Se o cliente vai consultar status, ele precisa saber o que cada estado significa e quando vale tentar de novo.
Exemplo simples
Imagine exportacao de CSV.
O usuário clica em “Exportar pedidos”.
Fluxo melhor:
- API cria um job
exp_123com statusqueued. - API publica mensagem com
job_id=exp_123. - API responde ao cliente com o id do job.
- Worker consome a mensagem e muda status para
processing. - Worker gera o arquivo, salva a URL e marca como
completed. - O cliente consulta
GET /exports/exp_123ou recebe webhook quando terminar.
Se o worker cair depois de metade do processo, o sistema precisa saber onde esta o job.
Se a mensagem reaparecer, o worker precisa entender se:
- ainda deve processar
- já concluiu
- falhou de forma definitiva
Sem esse desenho, a fila vira só uma desculpa elegante para esconder falta de controle.
Erros comuns
- Tratar fila como substituto de modelagem de estado.
- Enfileirar payload gigante em vez de referência para o trabalho.
- Fazer retry sem distinguir erro transitorio de erro permanente.
- Não ter idempotencia e depois sofrer com job duplicado.
- Não expor status para cliente, time de suporte ou operação.
Como um senior pensa
Quem tem mais experiência olha para job assíncrono como fluxo operacional, não só como padrão de código.
O pensamento costuma ser:
“Como essa intenção entra, como ela progride, como ela falha, como ela reaparece e como alguém descobre o que aconteceu?”
Essa pergunta obriga o sistema a ficar explicavel.
E sistema explicavel quase sempre e mais resiliente.
O que o entrevistador quer ver
Em entrevista, falar “eu usaria fila” quase nunca basta.
O avaliador quer ver se você enxerga o caminho inteiro.
Sinais bons:
- você fala de estado do job
- menciona
202 Acceptedou resposta equivalente - descreve retry com critério
- traz idempotencia para o worker
- explica como o cliente acompanha o resultado
Uma resposta forte costuma soar assim:
“Eu aceitaria a intenção, registraria o job, publicaria na fila e deixaria o worker processar com retry e idempotencia. O cliente não esperaria o trabalho terminar dentro da request. Ele consultaria o status ou receberia notificação.”
Fila desacopla latência. Estado e observabilidade desacoplam desespero.
Resumo rápido
O que vale manter na cabeça
- Fila e só um trecho do fluxo. O desenho bom inclui estado, retry, idempotencia e visibilidade.
- Job assíncrono começa quando a aplicação aceita a intenção e termina quando o resultado fica observável para alguém.
- Worker precisa lidar com repetição, falha transitoria e mensagem ruim sem virar caos operacional.
- Sem status claro para o cliente, o sistema só troca timeout por misterio.
Checklist de pratica
Use isto ao responder
- Consigo explicar o caminho completo entre request, fila, worker e resultado?
- Sei dizer onde idempotencia entra quando o job pode ser reprocessado?
- Consigo descrever retry, backoff e falha definitiva sem confundir tudo?
- Sei explicar por que job assinado por fila ainda precisa de estado persistido?
Você concluiu este artigo
Compartilhar esta página
Copie o link manualmente no campo abaixo.