RabbitMQ Priority Queues
A priority queue in RabbitMQ delivers higher-priority messages before lower-priority ones, regardless of arrival order. This lets critical messages jump ahead of less important ones, even if they arrive later. By default, all RabbitMQ queues treat every message equally (FIFO). Priority queues break from that rule intentionally.
The Emergency Room Analogy
In a hospital emergency room, patients are not treated in the order they arrived. A patient with a minor sprain waits while a patient with a heart attack gets seen immediately — even if the heart attack patient arrived an hour later. Priority queues apply the same triage logic to messages.
Enabling Priority on a Queue
To use priority, declare the queue with the x-max-priority argument. This sets the maximum priority level the queue supports. Any value from 1 to 255 is valid, though RabbitMQ recommends keeping the range small (1 to 5 or 1 to 10). Larger ranges use more memory per message.
channel.queue_declare(
queue='task-queue',
durable=True,
arguments={
'x-max-priority': 10 # supports priority levels 0 through 10
}
)
Publishing Messages with Priority
Set the priority property when publishing. The value must be between 0 and the queue's x-max-priority value. Higher numbers mean higher priority.
# Low priority task
channel.basic_publish(
exchange='',
routing_key='task-queue',
body='Process routine report',
properties=pika.BasicProperties(priority=1)
)
# High priority task
channel.basic_publish(
exchange='',
routing_key='task-queue',
body='Process critical payment',
properties=pika.BasicProperties(priority=9)
)
Even if the routine report message arrived in the queue first, the critical payment message is delivered to the consumer first because it has a higher priority value.
How Priority Works Internally
RabbitMQ maintains separate internal sub-queues for each priority level. A priority 10 sub-queue drains completely before priority 9 is served. Priority 9 drains before priority 8, and so on. If no high-priority messages exist, lower-priority messages are served normally.
Inside priority queue "task-queue": Priority 10: [urgent-job-A][urgent-job-B] Priority 5: [medium-job-X] Priority 1: [routine-job-1][routine-job-2][routine-job-3] Consumer delivery order: 1. urgent-job-A (priority 10) 2. urgent-job-B (priority 10) 3. medium-job-X (priority 5) 4. routine-job-1 (priority 1) 5. routine-job-2 (priority 1) 6. routine-job-3 (priority 1)
Priority Starvation
If your system constantly sends high-priority messages, low-priority messages may wait indefinitely — this is called starvation. A routine report that arrives Monday might still be sitting undelivered on Friday because high-priority messages never stop arriving.
Design priority queues with starvation in mind:
- Keep the priority range small (e.g., 1 to 3 or 1 to 5).
- Reserve the highest priority level for genuinely critical events only.
- Monitor the count of low-priority messages to detect growing starvation.
Priority with Prefetch
Set prefetch_count=1 on consumers when using priority queues. If prefetch is high (say 50), a consumer pulls 50 messages at once from the priority queue — including low-priority messages — before higher-priority messages have a chance to arrive. A low prefetch ensures the consumer always picks the highest-priority available message.
channel.basic_qos(prefetch_count=1)
Default Priority Value
If you publish a message to a priority queue without setting a priority, RabbitMQ treats it as priority 0 — the lowest possible. This is safe: non-priority-aware producers still work, and their messages wait behind anything with an explicit priority.
Real-World Examples
Customer Support Ticket System
Priority 3: Enterprise customer tickets (must respond in 1 hour) Priority 2: Pro customer tickets (respond in 4 hours) Priority 1: Free customer tickets (respond in 24 hours) All tickets go into one priority queue. Support agents always see enterprise tickets first.
Payment Processing
Priority 5: Retry failed payments (time-sensitive, affects revenue) Priority 3: New card payments Priority 1: Refund processing (less urgent)
Email Sending Service
Priority 10: Password reset emails (user is blocked, send instantly) Priority 5: Transactional receipts Priority 1: Newsletter / marketing emails
Memory Impact
Each priority level requires extra data structures inside RabbitMQ. Setting x-max-priority=255 is almost never a good idea — it creates 256 internal sub-queues even if you only use three levels. Use the smallest range that covers your real needs. A range of 1 to 5 covers almost every practical priority scenario.
Checking Priority in the Management UI
Open the Queues tab and look at the Features column. A priority queue shows Pri as one of its features. Click the queue to see its x-max-priority value in the arguments section. You can also use "Get messages" to peek at waiting messages and see each message's priority value.
Summary
Priority queues in RabbitMQ ensure that more important messages are consumed before less important ones, regardless of arrival order. Enable priority by declaring a queue with x-max-priority. Publish messages with a priority property value. Higher numbers are consumed first. Use a small priority range to avoid memory overhead and starvation of low-priority messages. Set prefetch_count=1 so consumers always pick the highest available priority. Priority queues are ideal for support tickets, payment retries, alerts, and any system where not all tasks are equally urgent.
