Voltar para o blog

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.