0
0
RabbitmqHow-ToBeginner · 4 min read

Retry with Dead Letter in RabbitMQ: Setup and Example

To implement retry with dead letter in RabbitMQ, configure a queue with a x-dead-letter-exchange and set message TTL for retry delay. When a message is rejected or expires, it moves to the dead letter exchange, which routes it back to the original queue for retry.
📐

Syntax

To set up retry with dead letter in RabbitMQ, you need to declare two queues and exchanges: the main queue and a dead letter queue. The main queue has these key arguments:

  • x-dead-letter-exchange: The exchange where rejected or expired messages are sent.
  • x-message-ttl: Time in milliseconds before a message expires and is dead-lettered.
  • x-dead-letter-routing-key: Optional routing key for dead letter messages.

The dead letter queue receives messages and can route them back to the main queue for retry.

python
channel.exchange_declare(exchange='dlx', exchange_type='direct')
channel.queue_declare(queue='main_queue', arguments={
  'x-dead-letter-exchange': 'dlx',
  'x-message-ttl': 5000,
  'x-dead-letter-routing-key': 'retry'
})
channel.queue_declare(queue='retry_queue', arguments={
  'x-dead-letter-exchange': '',
  'x-dead-letter-routing-key': 'main_queue',
  'x-message-ttl': 5000
})
channel.queue_bind(queue='retry_queue', exchange='dlx', routing_key='retry')
💻

Example

This example shows how to declare a main queue with a dead letter exchange and a retry queue. Messages rejected from the main queue are sent to the dead letter exchange, which routes them to the retry queue. The retry queue has a TTL and dead letters messages back to the main queue, creating a retry loop.

python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# Declare dead letter exchange
channel.exchange_declare(exchange='dlx', exchange_type='direct')

# Declare main queue with dead letter exchange and routing key
channel.queue_declare(queue='main_queue', arguments={
    'x-dead-letter-exchange': 'dlx',
    'x-dead-letter-routing-key': 'retry'
})

# Declare retry queue with TTL and dead letter back to main queue
channel.queue_declare(queue='retry_queue', arguments={
    'x-message-ttl': 5000,  # 5 seconds delay
    'x-dead-letter-exchange': '',  # default exchange
    'x-dead-letter-routing-key': 'main_queue'
})

# Bind retry queue to dead letter exchange
channel.queue_bind(queue='retry_queue', exchange='dlx', routing_key='retry')

# Publish a test message
channel.basic_publish(exchange='', routing_key='main_queue', body='Test message')

print('Message sent to main_queue')

connection.close()
Output
Message sent to main_queue
⚠️

Common Pitfalls

  • Missing dead letter exchange: Not setting x-dead-letter-exchange means messages won't be routed for retry.
  • No TTL on retry queue: Without x-message-ttl, messages won't expire and retry won't happen.
  • Infinite retry loops: Without a max retry count or delay increase, messages can retry forever causing resource issues.
  • Incorrect routing keys: Dead letter routing keys must match bindings or messages get lost.
python
## Wrong: No dead letter exchange
channel.queue_declare(queue='main_queue')

## Right: With dead letter exchange
channel.queue_declare(queue='main_queue', arguments={
  'x-dead-letter-exchange': 'dlx'
})
📊

Quick Reference

  • x-dead-letter-exchange: Exchange to send dead letter messages.
  • x-message-ttl: Time before message expires for retry delay.
  • x-dead-letter-routing-key: Routing key for dead letter messages.
  • Use a retry queue with TTL and dead letter back to main queue for retry.
  • Consider adding retry count headers to limit retries.

Key Takeaways

Set x-dead-letter-exchange on your main queue to route failed messages for retry.
Use x-message-ttl on the retry queue to delay retries before reprocessing.
Bind the retry queue to the dead letter exchange with the correct routing key.
Implement retry limits to avoid infinite retry loops and resource exhaustion.
Dead letter exchanges enable clean separation of failed message handling and retries.