A priority queue in RabbitMQ doesn’t actually prioritize messages; it just pretends to by putting higher-priority messages at the front of a regular queue.

Let’s see it in action. Imagine we have a high_priority_queue and a normal_priority_queue.

# Create the high priority queue with a max-length of 1000 messages
rabbitmqadmin declare queue name=high_priority_queue arguments='{"x-max-length":1000, "x-max-length-bytes":10485760, "x-message-ttl":86400000, "x-dead-letter-exchange":"dlx", "x-dead-letter-routing-key":"dlx-key", "x-max-priority":10}'

# Create the normal priority queue (default priority is 0)
rabbitmqadmin declare queue name=normal_priority_queue arguments='{"x-max-length":1000, "x-max-length-bytes":10485760, "x-message-ttl":86400000, "x-dead-letter-exchange":"dlx", "x-dead-letter-routing-key":"dlx-key"}'

# Publish a low priority message (priority 1) to the high priority queue
rabbitmqadmin publish exchange=amq.default routing_key=high_priority_queue payload="This is a low priority message" properties='{"priority":1}'

# Publish a high priority message (priority 9) to the high priority queue
rabbitmqadmin publish exchange=amq.default routing_key=high_priority_queue payload="This is a high priority message" properties='{"priority":9}'

# Publish a message to the normal queue
rabbitmqadmin publish exchange=amq.default routing_key=normal_priority_queue payload="This is a normal message"

When a consumer connects to high_priority_queue, it will retrieve the message with priority 9 before the message with priority 1. The normal_priority_queue behaves like a standard FIFO queue.

The core problem RabbitMQ’s priority queues solve is managing message delivery order when certain messages must be processed before others. This is common in systems where some tasks are time-sensitive (e.g., fraud alerts) while others are less so (e.g., daily reports). Without priorities, a flood of low-priority messages could inundate a consumer, delaying critical high-priority ones.

Internally, RabbitMQ handles priorities by maintaining multiple internal queues for each declared priority level (from 0 up to x-max-priority). When a message is published with a specific priority, it’s added to the corresponding internal queue. A consumer fetching messages from a priority-enabled queue will iterate through these internal queues, starting from the highest priority, and deliver messages from the first non-empty queue it finds. This ensures that higher-priority messages are always delivered before lower-priority ones, as long as the consumer is configured to respect these priorities. The x-max-priority argument on the queue declaration is crucial; without it, RabbitMQ treats all messages as priority 0, negating the prioritization mechanism.

The key configuration setting is x-max-priority on the queue itself. This argument dictates the highest priority level the queue will support. If you set x-max-priority: 10, you can then publish messages with priorities from 0 to 10. When publishing, you specify the priority using the priority property in the message attributes. Consumers don’t need special configuration to receive priority messages; they just fetch from the queue as usual. RabbitMQ’s broker handles routing the highest available priority message to the consumer.

A common pitfall is forgetting to set x-max-priority on the queue. If you publish messages with priority attributes but the queue doesn’t have x-max-priority configured, all messages will be treated as priority 0 and delivered in FIFO order. Another mistake is assuming priorities work across different queues; priorities are strictly within a single, priority-enabled queue. Also, if a consumer fetches messages without acknowledging them, and a higher priority message arrives, the lower priority message might be re-queued and then delivered after the higher priority one, which can be confusing if you expect strict FIFO within the same priority level.

When you have a priority queue with x-max-priority set, and a consumer fetches messages, the broker doesn’t just pick any message from the highest priority queue. It picks the oldest message from the highest priority queue that has messages. This means that within a given priority level, messages are still delivered in FIFO order.

The next challenge is managing message expiration in priority queues, especially when dealing with x-message-ttl.

Want structured learning?

Take the full Rabbitmq course →