A message can be requeued when consumer fails to process a message. It comes in handy when the message failed due a temporary glitch & can be processed successfully in next attempt or by a different consumer instance. The option whether to requeue or not can be controlled by requeue parameter while doing negative acknowledgement (basic.nack or basic.reject) from the consumer.
But now the question is where does RabbitMQ put this requeued message? Does the broker send the message at the tail end of the queue? That might sound normal. If we have a queue data structure & want to add some element to it, we would have to add it at the back end. But that is not the case with RabbitMQ. They have optimized requeuing so that the original message can be available for immediate reconsumption. This is what RabbitMQ said on their page.
When a message is requeued, it will be placed to its original position in its queue, if possible. If not (due to concurrent deliveries and acknowledgements from other consumers when multiple consumers share a queue), the message will be requeued to a position closer to queue head.
RabbitMQ tries to put the message into the same original position in the queue. In case of multiple consumers sharing the same queue, there can be concurrent deliveries & acknowledgements by other consumer instances. And it might not be possible for RabbitMQ broker to put the requeued message back to its original position. In that scenario, it will try to put the message near to queue front. That way the message would be ready for a quick redelivery.
For example, let’s consider a single consumer. Our queue has below messages:
3 -> 2 ->1
So consumer will read message 1 & starts processing it. Queue looks like:
3 -> 2
Now consumer requeues message 1 due to some failure. Queue looks like:
3 -> 2 -> 1
Now let’s consider we have two consumers. Our queue has below messages:
3 -> 2 -> 1
First consumer reads message 1 & starts processing it. Queue looks like:
3 -> 2
Second consumer concurrently consumes message 2 & starts processing it. Queue looks like:
3
First consumer fails to process message 1 & requeues it. Queue looks like:
3 -> 1
The examples are very simplistic for explaining the idea. Hope that helps.
Is there any way to configure it to put the failed message queue’s tail instead of queue’s head?
I don’t think RabbitMQ has option to do that. As a workaround, you can manually ack the failed message in a try/catch block (or similar to that) & put it back to the tail end of the queue by publishing it again. But that depends on the failure type & your use case.