Backend Development 5 min read

Implementing RabbitMQ Dead Letter Queues with Go

This article explains the concept of RabbitMQ dead letter queues, outlines the conditions that generate dead letters, provides step‑by‑step configuration instructions, and includes Go code examples for publishing messages with TTL and consuming from the dead‑letter queue to implement delayed processing.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
Implementing RabbitMQ Dead Letter Queues with Go

In many systems, task execution timeouts cause task status to remain unchanged, leading to poor user experience; a solution is to use RabbitMQ's dead letter queue (DLQ) mechanism.

A dead letter in RabbitMQ occurs when a message is negatively acknowledged with channel.basicNack or channel.basicReject without requeue, when the message exceeds its TTL, or when the queue length exceeds its maximum; such messages are then routed to a configured dead‑letter exchange.

To configure a DLQ, first create a dead‑letter exchange (e.g., exchange.dlx ) and bind two queues: queue.normal and queue.dlx . Then set the x-dead-letter-exchange argument on queue.normal to point to exchange.dlx and optionally configure a TTL for messages in queue.normal . Finally, publish messages to queue.normal ; when they expire they will be routed to queue.dlx for consumption.

Example Go code for publishing messages with a 5‑second TTL and specifying the dead‑letter exchange:

package main

import (
    "fmt"
    "github.com/streadway/amqp"
    "time"
)

func main() {
    conn, _ := amqp.Dial("amqp://user:password@host:ip/vhost")
    ch, _ := conn.Channel()
    body := "Hello World " + time.Now().Format("2021-10-20 15:04:05")
    fmt.Println(body)
    //声明交换器
    args := amqp.Table{"x-dead-letter-exchange": "exchange.dlx"}
    // 声明一个queue.normal队列,并设置队列的死信交换机为"exchange.dlx"
    q, _ := ch.QueueDeclare("queue.normal", true, false, false, false, args)
    ch.Publish("", q.Name, false, false, amqp.Publishing{
        Body:       []byte(body),
        Expiration: "5000", // 设置TTL为5秒
    })

    // defer 关键字
    defer conn.Close() // 压栈 后进先出
    defer ch.Close()   // 压栈 后进先出
}

Example Go code for consuming messages from the dead‑letter queue:

package main

import (
    "fmt"
    "github.com/streadway/amqp"
)

func main() {
    conn, _ := amqp.Dial("amqp://xxx:xxx@host:ip/vhost")
    ch, _ := conn.Channel()

    //监听queue.dlx队列
    msgs, _ := ch.Consume("queue.dlx", "", true, false, false, false, nil)

    for d := range msgs {
        fmt.Printf("receive: %s\n", d.Body) // 收到消息,业务处理
    }
}

In summary, using TTL combined with a dead‑letter queue provides an effective delayed‑queue solution for scenarios such as order timeout cancellation and retry mechanisms, and the provided Go examples demonstrate a practical implementation.

backendGoTTLMessage QueueRabbitMQDead Letter Queue
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

0 followers
Reader feedback

How this landed with the community

login 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.