Fila para processar pedidos em lote
Equipe AltiviaCloud · 6 de setembro de 2026 · 4 min de leitura
O laço sequencial demora e o Promise.all derruba o limite. Concorrência limitada, estado por item e o cálculo de quantos trabalhadores cabem.
Existe um momento em que a integração deixa de ser um pedido por vez. Chega uma planilha com quinhentas linhas, ou uma campanha dispara tudo junto, e o código que funcionava perfeitamente começa a falhar de formas estranhas.
O reflexo é enfileirar. O reflexo está certo — mas o ganho vem de detalhes que costumam ser pulados.
Por que o laço direto quebra
for (const linha of quinhentas) {
await criarPedido(linha);
}
Isso é sequencial. Se cada pedido leva um segundo, são oito minutos, e qualquer falha no meio deixa metade feito sem registro de onde parou.
A correção óbvia é paralelizar tudo:
await Promise.all(quinhentas.map(criarPedido));
E aí você abre quinhentas conexões simultâneas. Bate no limite de taxa na hora, e o limite derruba também os pedidos dos seus outros clientes, que não têm nada a ver com esse lote.
O certo está no meio: concorrência limitada.
Concorrência limitada, não ilimitada
Um número fixo de trabalhadores consumindo da fila. Cinco, dez, o que couber no limite do fornecedor.
Isso dá previsibilidade: você sabe quantas requisições estão em voo, sabe estimar o tempo total, e nunca ultrapassa o teto.
Como escolher o número: pegue o limite de requisições por minuto, divida pela duração média de uma chamada, e fique abaixo. Se o limite é 60 por minuto e cada chamada leva um segundo, um trabalhador já satura. Não adianta colocar dez.
Esse cálculo evita a conversa mais comum sobre desempenho, que é aumentar a concorrência para resolver lentidão causada por limite de taxa — o que só aumenta a taxa de erro.
A fila precisa lembrar onde parou
Fila em memória some quando o processo reinicia. E processo reinicia: deploy, falha, escala automática.
Se o lote de quinhentos morre no item duzentos, você precisa saber que os duzentos primeiros foram feitos. Sem isso, reprocessar significa duplicar.
Duas peças resolvem:
Estado por item, persistido. Cada linha do lote tem status próprio — pendente, em processamento, concluído, falho.
Uma chave de idempotência por item. Gerada antes da primeira tentativa e reenviada em todas. Assim, mesmo que o mesmo item seja tentado duas vezes, ele não vira dois pedidos.
Sem a segunda, reprocessar um lote parcialmente concluído é apostar.
Falha de um não pode parar o resto
A pior arquitetura de lote é a que interrompe tudo no primeiro erro. Uma linha com CPF inválido não deveria impedir as outras 499.
Separe o item que falhou, registre o motivo, e siga. No fim, entregue um relatório: tantos concluídos, tantos falharam, e por quê.
E distinga os dois tipos de falha, porque a ação é oposta:
Falha do item — dado inválido, saldo insuficiente. Não adianta repetir. Marque e informe.
Falha transitória — limite de taxa, fornecedor fora do ar, tempo esgotado. Devolva à fila com espera crescente.
Tratar as duas igual gera ou desperdício de tentativa, ou item perdido que deveria ter sido repetido.
Cuidado com a fila envenenada
Um item que sempre falha e sempre volta para a fila consome tentativas para sempre e pode travar o processamento dos outros.
O limite de tentativas resolve: depois de N vezes, o item sai para uma área de descarte, com o motivo registrado. Alguém olha depois.
Sem esse limite, um único registro malformado degrada o sistema inteiro em silêncio.
Dê visibilidade do progresso
Lote sem progresso visível gera a mesma pergunta várias vezes: "travou?".
O mínimo é: quantos itens no total, quantos concluídos, quantos falharam, e estimativa. Isso reduz chamado e permite ao cliente decidir se espera ou cancela.
E ofereça o cancelamento. Lote grande disparado por engano, sem como parar, é prejuízo que se acumula enquanto alguém procura o botão.
O que medir
Três números dizem se a fila está saudável:
- Tamanho da fila ao longo do tempo. Se cresce sem parar, a chegada supera o processamento.
- Tempo de espera do item mais antigo. É o que o cliente sente.
- Taxa de falha por tipo. Se a falha transitória sobe, o problema é o fornecedor. Se a de item sobe, é a origem dos dados.
Se o gargalo for limite de taxa, o caminho não é mais concorrência — é repetir com espera crescente e reduzir chamada inútil com cache no que muda devagar.
Se o lote for de números virtuais, conte com o teto de 20 pedidos por minuto por conta — é ele que dita o ritmo da fila, não a sua capacidade de processar.