Node.js › Message Queues (RabbitMQ & Kafka)

How would you implement a dead-letter exchange in RabbitMQ to handle messages that repeatedly fail processing?

Advanced

Answer

A dead-letter exchange (DLX) is configured on a queue to automatically receive messages that are rejected (nack'd without requeue), expire (via a message TTL), or exceed a queue's maximum length -- routing these problematic messages to a separate queue for inspection rather than losing them or endlessly retrying them in the main queue, mirroring the dead-letter queue concept discussed earlier for job queues but implemented at the message-broker level.
await channel.assertExchange('dlx', 'direct');
await channel.assertQueue('failed-orders');
await channel.bindQueue('failed-orders', 'dlx', '');

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

channel.consume('orders', (msg) => {
  try {
    processOrder(msg);
    channel.ack(msg);
  } catch (err) {
    channel.nack(msg, false, false); // false, false = don't requeue -- routes to the DLX instead
  }
});
Real-world example An order-processing queue configured with a dead-letter exchange automatically routes any order message that fails processing (due to a malformed payload, say) to a separate 'failed-orders' queue, where it's inspected and can be manually corrected and republished, rather than being silently dropped or endlessly reprocessed and failing in a loop.

Common follow-ups: How do you distinguish between a transient failure worth retrying automatically versus a permanent failure that should go straight to the dead-letter queue?;What monitoring would you set up to alert when messages start accumulating in a dead-letter queue?