RabbitMQ dead letter exchange never getting messages

If you want all your queues to have same dead letter exchange it is easier to set a general policy:

sudo rabbitmqctl -p /my/vhost/path set_policy DLX ".*" '{"dead-letter-exchange":"MyExchange.DEAD"}' --apply-to queues

Gentilissimo Signore was kind enough to answer my question on Twitter. The problem is that if your dead letter exchange is setup as DIRECT you must specify a dead letter routing key. If you just want all your NACKed message to go into a dead letter bucket for later investigation (as I do) then your dead letter exchange should be setup as a FANOUT.

Here are the updated steps that work:

  1. Create new FANOUT exchange with the name "dead.letter.test"
  2. Create new queue "dead.letter.queue"
  3. Bind "dead.letter.queue" to "dead.letter.test"
  4. Create new queue "test1" with the dead letter exchange set to "dead.letter.test"
  5. Send a message into "test1"
  6. Nack (with requeue = false) the message in "test1"

If you want to use custom routing key on dead letter exchange you have to set x-dead-letter-routing-key when declaring working queue (in your case it is test1), otherwise default routing key will be used. In your case RabbitMQ broker detects cycling and simply drop rejected messages.

What you need is to have x-dead-letter-exchange=dead.letter.test and x-dead-letter-routing-key=dead.letter.queue arguments set on test1 queue.


Dead Letter Exchange without routing key and with direct exchange


Follow the steps these will work for sure:-
1. Create a new queue named 'dead_queue'.
2. Create an exchange named 'dead_exchange' and type of exchange should be 'direct'.
3. Bind 'dead_queue' and 'dead_exchange' without routing key.
4. Create a new queue named 'test_queue' and set its 'x-dead-letter-exchange' name as 'dead_exchange'
5. Create an exchange named 'test_exchange' and type of exchange should be 'direct'
6. Bind 'test_exchange' and 'test_queue' without routing key.

And at last we will check it. For this publish something on 'test_exchange' with argument 'expiration' set to 10000. After this when a message is publish on 'test_exchange' it will go to 'test_queue' and when a message is expired with in a queue it will look for DLX Parameter(Dead Letter Exchange name) there that message find the name 'dead_exchange' then that message will reach 'dead_exchange' deliver it to 'dead queue' .. If still you have any problem regarding this and if i miss understood your problem... write your problem i will surely look over it... Thanks..

Note: Must publish the message on 'test_exchange' because that test_queue and test_exchange binding is without routing key and it will work fine but If you publish message on 'test_queue' default exchange and routing key will be used.Then after expiration of message queue tries to deliver that dead message to dead_exchange with some default routing key and message will not go to that queue.