skip to content
Alvin Lucillo

Consumer timeout in action

/ 3 min read

Below is a snippet from a worker/consumer. The thing to note here is that auto-ack is false and the message isn’t acknowledged when received. The publisher program, which is not provided below, just plainly sends the message.

The gist of this journal is that when a consumer doesn’t acknowledge/ack a message, the message remains invisible to other consumers until the consumer timeout lapsed. At that point, the message becomes available for other consumers to receive.

	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")

	chClose := make(chan *amqp.Error, 1)
	ch.NotifyClose(chClose)
	consCancel := make(chan string, 1)
	ch.NotifyCancel(consCancel)

	var forever chan struct{}

	go func() {
		for {
			select {
			case err := <-chClose:
				if err != nil {
					log.Printf("Channel closed: %v", err)
				} else {
					log.Printf("Channel closed")
				}
				return
			case tag := <-consCancel:
				log.Printf("Consumer canceled: %s", tag)
				return
			}
		}
	}()

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

	log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
	<-forever

We set a consumer timeout of 15s:

 docker exec -it rabbitmq rabbitmqadmin list policies
┌──────────────────┬───────┬──────────────┬──────────┬──────────┬─────────────────────────┐
 name vhost pattern apply_to priority definition
├──────────────────┼───────┼──────────────┼──────────┼──────────┼─────────────────────────┤
 ack-timeout-demo / ^task_queue$  queues 0 consumer-timeout: 15000

└──────────────────┴───────┴──────────────┴──────────┴──────────┴─────────────────────────┘

Publisher sends a message

go run .
2026/01/13 21:05:31  [x] Sent hello

Worker 1 is run. The message is received but not acknowledged. The message is not redelivered. The terminal remains and is not exited.

go run ./worker
2026/01/13 21:05:36  [*] Waiting for messages. To exit press CTRL+C
2026/01/13 21:05:36 Received a message: hello (redelivered=false)

Worker 2 is run as well. No message is received yet because nothing is in the queue. The terminal remains and is not exited.

go run ./worker
2026/01/13 21:05:40  [*] Waiting for messages. To exit press CTRL+C

After a minute or so in worker 1 terminal, the channel is closed, as described by the error.

go run ./worker
2026/01/13 21:05:36  [*] Waiting for messages. To exit press CTRL+C
2026/01/13 21:05:36 Received a message: hello (redelivered=false)
2026/01/13 21:06:38 Channel closed: Exception (406) Reason: "PRECONDITION_FAILED - delivery acknowledgement on channel 1 timed out. Timeout value used: 15000 ms. This timeout value can be configured, see consumers doc guide to learn more"

At the same time, worker 2 terminal indicates that a message is received, and it’s redelivered message.

go run ./worker
2026/01/13 21:05:40  [*] Waiting for messages. To exit press CTRL+C
2026/01/13 21:06:38 Received a message: hello (redelivered=true)