skip to content
Alvin Lucillo

Listing unacknowledged messages

/ 2 min read

The code snippet below is from a worker that consumes messages from a queue. For now, just imagine that there’s another Go program that publishes messages to this.

	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		false,  // auto-ack
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	failOnError(err, "Failed to register a consumer")

	var forever chan struct{}

	go func() {
		for d := range msgs {
			log.Printf("Received a message: %s", d.Body)
			dotCount := bytes.Count(d.Body, []byte("."))
			t := time.Duration(dotCount)
			time.Sleep(t * time.Second)
			log.Printf("Done")
			// d.Ack(false)
		}
	}()

We ran the publisher Go program that sent the ‘hello’ payload

go run .
2026/01/12 20:47:01  [x] Sent hello

Then we ran the worker (with snippet from above) that received the same message payload.

go run ./worker
2026/01/12 20:47:05  [*] Waiting for messages. To exit press CTRL+C
2026/01/12 20:47:05 Received a message: hello
2026/01/12 20:47:05 Done

Now when we list the unacknowledged message, we can see that there’s one. This is because since we set auto-acknowledge to false, we need to mark a message acknowledged once it’s processed. Every time the consumer client is rerun, it will pick up this message but not mark is as acknowledged. To fix this, just uncomment d.Ack... above.

docker exec -it rabbitmq rabbitmqctl list_queues name messages_ready messages_unacknowledged
Timeout: 60.0 seconds ...
Listing queues for vhost / ...
name    messages_ready  messages_unacknowledged
task_queue      0       1