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: trueem 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.




