Home/Learn/RabbitMQ/Prefetch Count & QoS

Prefetch Count & QoS

Intermediate
Reliability

basicQos limits the number of unacknowledged messages a consumer can hold; low prefetch ensures even work distribution and prevents a slow consumer from monopolising the queue.

Overview

By default RabbitMQ pushes messages to a consumer as fast as the network allows. Without a prefetch limit, a fast consumer could grab hundreds of messages while a slow one sits idle — defeating the purpose of a worker-queue pattern. `basic.qos` (Quality of Service) sets the maximum number of unacknowledged messages the broker will deliver to a single channel before waiting for an ack. Setting `prefetchCount = 1` guarantees round-robin-like fairness: a consumer only gets a new message once it has acknowledged the previous one. Higher prefetch values improve throughput but reduce fairness. In Spring AMQP the equivalent is `SimpleMessageListenerContainer.setPrefetchCount()`.

How basicQos Works

The broker tracks a per-channel "unacked" counter. Each delivered message increments it; each ack decrements it. When the counter reaches `prefetchCount`, the broker stops delivering on that channel until an ack arrives. Setting `global=false` (the default) applies the limit per consumer on the channel; `global=true` applies it to the whole channel. Most use cases want per-consumer limits.

Java — AMQP client basicQos
// AMQP Java client
Channel channel = connection.createChannel();
// Allow at most 5 unacknowledged messages per consumer
channel.basicQos(5 /*, global= false (default) */);

channel.basicConsume("orders", false, (tag, delivery) -> {
    try {
        process(delivery.getBody());
        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    } catch (Exception e) {
        // requeue=false → routed to DLX if configured
        channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, false);
    }
}, tag -> {});

Spring AMQP Prefetch Configuration

Spring Boot's auto-configured `SimpleRabbitListenerContainerFactory` exposes `spring.rabbitmq.listener.simple.prefetch` in application.properties. For fine-grained control, customise the factory bean directly. The default prefetch in Spring AMQP is 250 — great for throughput but can cause imbalance with slow tasks; lower it for CPU-intensive or long-running consumers.

Spring Boot — prefetch config
# application.properties
spring.rabbitmq.listener.simple.prefetch=1        # fair dispatch
spring.rabbitmq.listener.simple.acknowledge-mode=manual

# --- OR via Java config ---
@Bean
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
        ConnectionFactory cf) {
    var factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(cf);
    factory.setPrefetchCount(5);
    factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    return factory;
}

Choosing the Right Prefetch Value

There is no single "right" prefetch. For **long tasks** (> 1 s each), use prefetch=1 for fairness. For **short tasks** (< 10 ms), use prefetch=10–100 to keep consumers busy without extra round trips. For **batch consumers** set prefetch equal to the batch size. Monitor consumer utilisation with `rabbitmq_queue_consumers` and `rabbitmq_queue_messages_unacknowledged` Prometheus metrics and tune accordingly.

Prometheus — starvation alert
# Prometheus alert — consumer sitting idle because prefetch too low
- alert: RabbitConsumerStarved
  expr: |
    rabbitmq_queue_messages_ready > 100
    and rabbitmq_queue_consumers > 0
    and rabbitmq_queue_messages_unacknowledged == 0
  for: 2m
  annotations:
    summary: "Consumers idle but queue has {{ $value }} messages — raise prefetch"

Key Points to Remember

  • 1basicQos(n) stops the broker delivering more than n unacked messages to a consumer
  • 2prefetch=1 gives the fairest distribution; higher values improve throughput
  • 3Spring AMQP default prefetch is 250 — lower it for slow/CPU-heavy tasks
  • 4global=false (default) applies the limit per consumer; global=true per channel
  • 5Always combine manual ack with a sensible prefetch — auto-ack ignores QoS
  • 6Monitor unacked message counts in Prometheus to find the optimal value

Interview Questions

Sign in to ask Aria
1

What happens if you set prefetchCount to 0 in RabbitMQ?

MediumThoughtworks
2

Explain the difference between global=true and global=false in basicQos.

HardGoldman Sachs
3

Why does the default Spring AMQP prefetch of 250 cause problems with slow consumers?

MediumDeliveroo
4

How would you choose an optimal prefetch count for a queue processing image thumbnails?

MediumAdobe
5

Does prefetch affect consumers using auto-ack mode?

EasyZalando

Ask Aria about Prefetch Count & QoS

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…