What Causes Messages to be Dead Lettered in RabbitMQ
A message in RabbitMQ is dead lettered when it is rejected or negatively acknowledged with
requeue=false, when it expires due to TTL (time-to-live), or when the queue reaches its maximum length and discards messages. These messages are then routed to a configured dead-letter-exchange for further handling.Syntax
Dead lettering in RabbitMQ involves setting up a dead-letter-exchange on a queue. Messages get dead lettered when:
- They are
nacked orrejected withrequeue=false. - They expire due to TTL (time-to-live) settings.
- The queue exceeds its maximum length and discards messages.
Example queue argument to enable dead lettering:
json
{
"x-dead-letter-exchange": "my-dead-letter-exchange"
}Example
This example shows how to declare a queue with a dead-letter exchange and how a rejected message is dead lettered.
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 queue with dead-letter exchange args = {'x-dead-letter-exchange': 'dlx'} channel.queue_declare(queue='main_queue', arguments=args) # Declare dead-letter queue channel.queue_declare(queue='dead_letter_queue') channel.queue_bind(queue='dead_letter_queue', exchange='dlx', routing_key='') # Publish a message channel.basic_publish(exchange='', routing_key='main_queue', body='Test Message') # Consume and reject message without requeue to dead letter it method_frame, header_frame, body = channel.basic_get('main_queue') if method_frame: print(f"Received: {body.decode()}") channel.basic_reject(delivery_tag=method_frame.delivery_tag, requeue=False) else: print('No message received') connection.close()
Output
Received: Test Message
Common Pitfalls
Common mistakes when working with dead lettering include:
- Not setting
requeue=falsewhen rejecting messages, causing them to be requeued instead of dead lettered. - Forgetting to declare or bind the dead-letter exchange and queue, so dead-lettered messages are lost.
- Not configuring TTL or max length properly, missing automatic dead lettering triggers.
python
channel.basic_reject(delivery_tag=method_frame.delivery_tag, requeue=True) # Wrong: message requeued, not dead lettered channel.basic_reject(delivery_tag=method_frame.delivery_tag, requeue=False) # Correct: message dead lettered
Quick Reference
| Cause | Description |
|---|---|
| Message rejected or nacked with requeue=false | Message is sent to dead-letter exchange instead of requeued. |
| Message TTL expired | Message expires and is dead lettered automatically. |
| Queue max length exceeded | Oldest messages are dead lettered or dropped when queue is full. |
Key Takeaways
Messages get dead lettered when rejected with requeue=false, expired, or when queue limits are exceeded.
Always configure a dead-letter exchange and bind a dead-letter queue to capture dead-lettered messages.
Use message TTL and queue length limits to control automatic dead lettering.
Reject messages with requeue=false to move them to the dead-letter queue instead of retrying.
Verify dead-letter setup to avoid losing messages silently.