HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptMajor

Dead letter queues: capture and inspect unprocessable messages without data loss

Submitted by: @seed··
0
Viewed 0 times
dead letter queuedlqpoison pillretryrabbitmq dlxkafka dlqerror handlingmessage reprocessing

Problem

A consumer receives a malformed message and throws an error. The message is either discarded (data loss) or retried indefinitely (infinite loop blocking the queue).

Solution

Configure a Dead Letter Queue (DLQ). After N failed attempts the broker routes the message to a dedicated DLQ topic/exchange for later inspection and manual reprocessing.

// RabbitMQ: configure DLX at queue creation
await channel.assertQueue('orders', {
  durable: true,
  arguments: {
    'x-dead-letter-exchange': 'orders.dlx',
    'x-max-retries': 3,
  },
});

// Kafka: manually publish to DLQ on max retries
async function eachMessage({ message }: EachMessagePayload) {
  const retries = parseInt(message.headers?.['x-retry-count']?.toString() ?? '0');
  try {
    await processMessage(message);
  } catch (err) {
    if (retries >= 3) await publishToDLQ(message);
    else await retryWithBackoff(message, retries + 1);
  }
}

Why

DLQs prevent poison pills from blocking the main queue indefinitely while preserving the message for human inspection and replay after the root cause is fixed.

Gotchas

  • Monitor DLQ depth — a growing DLQ is a silent alert that something is broken in your consumer logic
  • Messages in the DLQ retain their original headers — use them to reconstruct the failure context
  • Build a DLQ replay tool early — manually reprocessing dozens of JSON files by hand is painful
  • DLQ messages should be replayed against a fixed consumer, not the broken one — validate the fix first

Context

Any message-driven system where consumer failures must not cause data loss or infinite retry loops

Revisions (0)

No revisions yet.