Master RabbitMQ Dead Letter Queues: When and How Messages Are Redirected

This guide explains RabbitMQ dead‑letter queues, covering the conditions that turn messages into dead letters, how to configure exchanges and queues with x‑dead‑letter‑exchange, TTL, and max‑length, and provides step‑by‑step Spring Boot code examples for testing each scenario.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master RabbitMQ Dead Letter Queues: When and How Messages Are Redirected

Environment: Spring Boot 2.3.10, RabbitMQ 3.8.12, Erlang 23.2.5

Dead Letter Queue Introduction

Messages become dead letters when any of the following occurs:

Consumer calls basic.reject or basic.nack with requeue=false.

Message TTL expires (queue created with x-message-ttl) or the queue exceeds its length limit.

Note: Queue expiration set by x-expires does not generate dead letters.

A dead‑letter exchange is a normal exchange and can be of any type.

When creating a queue, specify x-dead-letter-exchange and optionally x-dead-letter-routing-key to redirect dead letters to the designated exchange.

Setup Environment

Create the normal business exchange and queue.

Declare a topic exchange named business-exchange.

Declare a fanout exchange named dead-exchange (the dead‑letter exchange).

Create business-queue and bind it to business-exchange, setting x-dead-letter-exchange to the previously created dead‑letter exchange (no routing key needed because the dead‑letter exchange is fanout).

Test

Method 1: Consumer rejects a message using basic.reject or basic.nack.

Send message endpoint:

@GetMapping("/sendDeadLetter")
public Object sendDeadLetter(String msg) {
    ms.sendDeadLetter(msg);
    return "success";
}
public void sendDeadLetter(String msg) {
    logger.info("准备发送消息:{}", msg);
    rabbitTemplate.convertAndSend("business-exchange", "be.1", msg);
}

Message listener:

@Component
public class MessageListener {
    @RabbitListener(queues = {"bussiness-queue"})
    @RabbitHandler
    public void listener1(Message message, Channel channel) {
        System.out.println("接受到消息.....income");
        byte[] body = message.getBody();
        MessageProperties mps = message.getMessageProperties();
        String content = new String(body, Charset.forName("UTF-8"));
        try {
            // Simulate reject scenario
            if ("1".equals(content)) {
                System.out.println("拒绝消息:1");
                channel.basicReject(mps.getDeliveryTag(), false);
                return;
            }
            System.out.println("接受到消息来自交换机: 【" + mps.getReceivedExchange() + "】, 队列:【" + mps.getConsumerQueue() + "】:
\t\t内容: " + content);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                channel.basicReject(mps.getDeliveryTag(), false);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}

When the message content is "1", the listener rejects it, and the message is routed to the dead‑letter queue.

Sending normal messages shows they are delivered to the original queue, while rejected messages appear in the dead‑letter queue.

Method 2: Message TTL Expiration

Recreate business-queue with x-message-ttl=10000 (10 seconds) and bind it to the exchange.

After 10 seconds the expired messages are automatically transferred to the dead‑letter queue.

Method 3: Queue Length Limit

Delete the existing bussiness-queue and recreate it with x-max-length=3. Any message beyond the third is sent to the dead‑letter queue.

Publish three messages; they stay in the queue. Publishing a fourth message causes the excess to be redirected to the dead‑letter queue.

These three methods demonstrate how RabbitMQ dead‑letter queues work and the situations that cause messages to be forwarded.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendSpring BootMessage QueueRabbitMQDead Letter Queue
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.