RabbitMQ dead lettering routes messages from a queue to a configured dead-letter exchange after events such as rejection/nack without requeue, expiry, queue length limits, or a quorum-queue delivery limit. A dead-letter queue is an ordinary queue bound to that exchange; it is not automatic recovery.

Configure with policies

Prefer policies for dead-letter exchange and routing-key configuration because policies can change without redeploying applications or deleting queues. Hardcoded queue arguments are appropriate only when immutability is intentional and operationally managed.

Ensure the declaring identity has required permissions and that exchanges/queues exist as expected. Validate routing; an unroutable dead-lettered message can be lost depending on configuration and safety path.

Classify failures before retrying

  • Transient: timeout, throttling, or dependency unavailability that may recover.
  • Permanent: invalid schema, unsupported operation, or failed business rule.
  • Unknown: requires investigation before repeated side effects.

Retry only failures likely to recover. Use bounded attempts, exponential or scheduled backoff with jitter where appropriate, a maximum age, and an explicit terminal path. Immediate requeue loops can consume CPU/network and starve healthy work.

Choose a retry mechanism explicitly

Applications can republish to delay queues with TTL and dead-letter routing, use delayed-delivery plugins when approved and supported, or schedule retries outside RabbitMQ. Queue-level TTL and per-message expiry have ordering and head-of-line implications. Document timing accuracy, durability, plugin dependence, and failure behavior.

Make consumers idempotent

RabbitMQ acknowledgments and confirms do not make external side effects exactly once. Assign a stable operation/message identifier, validate schema, record processed outcomes transactionally where possible, and make repeat handling safe. Define what happens when the database commit succeeds but acknowledgment fails.

Preserve diagnostic context safely

Record original message identity, source, attempt, timestamps, failure class, sanitized error, schema/version, and trace correlation. RabbitMQ adds dead-letter history headers, but header growth is bounded and transformations occur. Do not place secrets or unrestricted personal data in payloads, headers, or error logs.

Control replay

  1. Fix or isolate the root cause.
  2. Choose a bounded cohort by reason, source, schema, and time.
  3. Validate authorization and retention.
  4. Replay at a controlled rate with idempotency and current compatibility checks.
  5. Monitor success, repeated failure, downstream load, and side effects.
  6. Stop and reconcile when acceptance limits fail.

Monitor the terminal path

Track retry volume, age, attempt distribution, terminal queue depth, routing failures, replay outcomes, poison-message rate, and ownership/service objectives. Alert on sustained accumulation and oldest-message age, not every individual failure. Apply RabbitMQ monitoring.

Secure payloads and replay authority with RabbitMQ security, and validate exchange/queue bindings using routing patterns.

Originally published November 30, 2015; technically reviewed and substantially updated September 4, 2026.