Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

RabbitMQ no Node.js: filas, ACK e retries

Atualizado em: 16 de outubro de 2026

Rack de servidores processando fluxos de dados no Node.js

RabbitMQ no Node.js permite distribuir tarefas e eventos por filas com confirmações, roteamento, retries e controle de concorrência. O broker implementa o protocolo AMQP e oferece exchanges, queues, bindings e acknowledgements para construir processamento assíncrono confiável.

Uma integração robusta precisa tratar reconexão, canais, mensagens duplicadas, backpressure e dead letter queues. Apenas publicar JSON em uma fila não garante que o fluxo sobreviva a falhas.

Conceitos principais

  • Producer: publica mensagens;
  • Exchange: recebe e roteia;
  • Queue: armazena mensagens;
  • Binding: conecta exchange e fila;
  • Consumer: processa mensagens;
  • Ack: confirma processamento.

Conexão e canal

import amqp from 'amqplib';

const connection = await amqp.connect(process.env.AMQP_URL);
const channel = await connection.createConfirmChannel();

await channel.assertExchange('orders', 'topic', {
  durable: true
});

Uma conexão pode manter vários canais. Não abra conexão por mensagem. Crie ciclo de vida explícito e reconecte com backoff.

Declarando fila

await channel.assertQueue('billing.order-created', {
  durable: true,
  arguments: {
    'x-dead-letter-exchange': 'orders.dlx'
  }
});

await channel.bindQueue(
  'billing.order-created',
  'orders',
  'order.created.v1'
);

Publicação persistente

const event = {
  id: crypto.randomUUID(),
  type: 'order.created.v1',
  occurredAt: new Date().toISOString(),
  data: { orderId: 'o-1', totalCents: 15990 }
};

channel.publish(
  'orders',
  event.type,
  Buffer.from(JSON.stringify(event)),
  {
    persistent: true,
    contentType: 'application/json',
    messageId: event.id,
    timestamp: Date.now()
  }
);
await channel.waitForConfirms();

Publisher confirms informam que o broker aceitou a publicação. Eles não significam que um consumidor concluiu o trabalho.

Consumidor com ack manual

await channel.prefetch(20);

await channel.consume('billing.order-created', async message => {
  if (!message) return;
  try {
    const event = JSON.parse(message.content.toString('utf8'));
    await processar(event);
    channel.ack(message);
  } catch (error) {
    const transitório = classificarErro(error) === 'transient';
    channel.nack(message, false, transitório);
  }
}, { noAck: false });

Com noAck: false, a mensagem só é removida após confirmação.

Prefetch

prefetch limita mensagens não confirmadas por consumidor. Ajuste conforme custo do processamento e capacidade do banco. Valor alto pode sobrecarregar dependências; baixo pode reduzir throughput.

Retries

Reencaminhar imediatamente para a mesma fila pode criar loop rápido. Prefira filas de retry com TTL e dead-letter routing.

await channel.assertQueue('billing.retry.30s', {
  durable: true,
  arguments: {
    'x-message-ttl': 30000,
    'x-dead-letter-exchange': 'orders',
    'x-dead-letter-routing-key': 'order.created.v1'
  }
});

Inclua contador de tentativas em headers e limite o número total.

Dead Letter Queue

Mensagens com erro permanente ou tentativas esgotadas devem ir para DLQ. Mantenha payload original, motivo e histórico de tentativas.

Idempotência

Uma mensagem pode ser entregue novamente se o consumidor cair depois de executar o efeito e antes do ack.

await db.transaction(async trx => {
  const novo = await inbox.registrar(event.id, trx);
  if (!novo) return;
  await faturas.criar(event.data, trx);
});

Exchanges

  • direct: igualdade exata da routing key;
  • topic: padrões como order.*;
  • fanout: envia para todas as filas vinculadas;
  • headers: roteia por cabeçalhos.

Escolha o tipo mais simples que atende ao fluxo.

Mensagens grandes

Não use RabbitMQ como armazenamento de arquivos. Salve o objeto em storage e envie referência, tamanho, checksum e metadados.

Backpressure do publisher

channel.publish() pode retornar false. Aguarde o evento drain antes de continuar produzindo em alta taxa.

Reconexão

Ao perder conexão, canais e consumers também são perdidos. Recrie topologia e assinaturas após reconectar. Use backoff com jitter e evite loops apertados.

Graceful shutdown

Ao receber sinal, pare de aceitar trabalho, cancele consumers, aguarde mensagens em andamento e feche canal e conexão.

Segurança

Use TLS, usuários com permissões mínimas, virtual hosts separados e rotação de credenciais. Não registre conteúdo sensível das mensagens.

Observabilidade

Monitore profundidade da fila, mensagens prontas e não confirmadas, taxa de publish/ack, redeliveries, conexões, canais e idade da mensagem mais antiga.

Testes

  • publicação com confirm;
  • falha antes e depois do efeito;
  • redelivery;
  • retry com atraso;
  • DLQ;
  • consumidores concorrentes;
  • reconexão;
  • shutdown durante processamento.

Erros comuns

  • conexão por mensagem;
  • noAck: true em trabalho crítico;
  • sem prefetch;
  • retry infinito;
  • consumidor não idempotente;
  • publisher sem confirms;
  • fila não durável;
  • sem monitoramento.

Conclusão

RabbitMQ no Node.js oferece filas e roteamento flexível para tarefas e eventos. Confiabilidade depende de publisher confirms, ack manual, retries controlados, DLQ e idempotência.

Combine o broker com Outbox Pattern no Node.js e Event-Driven Architecture no Node.js.

Consulte a documentação oficial do RabbitMQ e o guia do amqplib.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita