RabbitMQ’s prefetch count is a surprisingly blunt instrument that actually limits how much work a consumer can do, not how much it can receive.

Let’s see this in action. Imagine a simple queue my_queue with a few messages.

# Producer sending messages
rabbitmqadmin publish exchange="" routing_key="my_queue" payload="message_$(printf "%03d" $i)"

# Consumer with prefetch_count=1
# (Using amqplib for example, actual client code will vary)
channel.prefetchCount = 1
channel.consume('my_queue', (message) => {
  console.log(`Received: ${message.content.toString()}`);
  // Simulate work
  setTimeout(() => {
    channel.ack(message);
    console.log(`Acknowledged: ${message.content.toString()}`);
  }, 5000); // 5 second processing time
});

If you run this consumer with prefetchCount = 1, even if you have 10 messages in the queue, the consumer will only pull one message at a time. It won’t ask for the next message until it has acknowledged the first one. This means your consumer is effectively single-threaded for processing, despite the name suggesting it’s about how much it prefetches.

Now, what happens if we increase prefetchCount to, say, 10?

// Consumer with prefetch_count=10
channel.prefetchCount = 10
channel.consume('my_queue', (message) => {
  console.log(`Received: ${message.content.toString()}`);
  // Simulate work
  setTimeout(() => {
    channel.ack(message);
    console.log(`Acknowledged: ${message.content.toString()}`);
  }, 5000); // 5 second processing time
});

With prefetchCount = 10, the consumer will now fetch up to 10 unacknowledged messages from the queue. If messages arrive quickly, it will keep pulling them until it has 10 outstanding. Only once it starts acknowledging messages will it request more. This allows for higher throughput because the network and processing can be more fully utilized. The consumer is actively requesting messages in batches, not passively receiving them.

The core problem prefetchCount solves is preventing a single, slow consumer from hogging all messages in a queue, starving other consumers. If a consumer is very slow to process messages, and prefetchCount is high, it could theoretically grab all messages. By keeping prefetchCount low, you ensure that messages are distributed more evenly among multiple consumers.

Internally, RabbitMQ tracks the number of unacknowledged messages delivered to each consumer. When a consumer sends a basic.consume or basic.get_empty (for basic.get) and has fewer unacknowledged messages than its prefetchCount, RabbitMQ will deliver more messages from the queue until the count reaches the limit or the queue is empty. The prefetchCount is a per-channel setting, meaning each consumer connection can have its own.

The magic number for prefetchCount is often related to the expected processing time of a single message and the number of consumer instances you have. A common starting point is prefetchCount = 2 * num_cores. This aims to keep all CPU cores busy processing messages without overwhelming the system or the network. If your processing involves I/O, you might need a higher prefetchCount to ensure the CPU isn’t waiting idly.

If you set prefetchCount too high, you risk a slow consumer holding onto a large number of messages. If that consumer crashes, those messages will be redelivered to other consumers, potentially causing a backlog and impacting overall system responsiveness. Conversely, setting it too low can lead to underutilization of your consumer resources, as they spend more time waiting for the next message than processing.

The prefetch_count setting is applied on a per-channel basis when you establish a consumer. It’s crucial to understand that this is a limit on how many messages RabbitMQ will deliver to a consumer before it receives an acknowledgment. It’s not about how many messages the consumer can buffer internally, but how many the broker is willing to send in anticipation of work. If a consumer receives a message and immediately acknowledges it, it will then request another one, up to its prefetch limit.

The key takeaway is that prefetchCount is about managing the flow of messages from the broker to the consumer, ensuring that the broker doesn’t overwhelm a consumer and that messages are distributed efficiently.

Want structured learning?

Take the full Rabbitmq course →