RabbitMQ Priority Queue Design Prompt
Design a RabbitMQ priority queue that actually prioritizes — choosing the right number of priority levels, avoiding starvation, and understanding why prefetch can defeat the whole scheme.
- Target user
- Backend and platform engineers building tiered message handling
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior platform engineer who has built RabbitMQ priority queues that behave correctly under load. Help me design mine so high-priority messages truly jump the line. I will provide: - The priority tiers I need and the traffic mix per tier (e.g., 5% urgent, 95% normal) [DESCRIBE] - Whether low-priority messages must eventually be processed (anti-starvation requirement) [DESCRIBE] - Consumer setup: consumer count, current prefetch, processing time [DESCRIBE] - Expected backlog depth and broker version [DESCRIBE] Your job: 1. **Pick the number of priority levels** — explain that each priority level adds overhead and that a small number (e.g., 2-3) is almost always enough; map my tiers onto `x-max-priority` without inventing ten levels I'll never use. 2. **Explain the prefetch interaction** — this is the killer: priority only orders messages WAITING in the queue. If a consumer has a high prefetch, it has already pulled a batch of low-priority messages into its local buffer, and a newly arrived urgent message waits behind them. Recommend prefetch = 1 (or very low) so priority is honored at delivery time. 3. **Starvation** — describe how a flood of high-priority messages can starve low-priority ones forever, and whether my requirement needs an anti-starvation mechanism (aging, separate queues, or rate-limiting the high tier). 4. **Single queue vs separate queues** — compare a priority queue against two plain queues with weighted consumers, and recommend which fits my mix. 5. **Validate** — confirm `x-max-priority` is set at declare time (it can't be added later), then load-test that urgent messages are processed ahead of normal ones with the chosen prefetch. Output as: (a) the priority-level count with reasoning, (b) the declare arguments and the required low prefetch, (c) the starvation handling, (d) single-vs-separate-queue verdict, (e) the load test that proves priority works. Load-test the priority behavior on staging with a realistic traffic mix and the production prefetch. Confirm urgent messages actually preempt normal ones — a high prefetch silently defeats priority, and that only shows up under load, not in a quick functional test.
Why this prompt works
Priority queues are deceptively simple to declare and surprisingly easy to render useless. The trap that this prompt centers on is the prefetch interaction: priority only orders messages that are still sitting in the queue. The moment a consumer with a generous prefetch pulls a batch of normal-priority messages into its local buffer, a freshly arrived urgent message has to wait behind them — the queue can’t reach into a consumer’s buffer to reorder. Most “our priority queue doesn’t prioritize” tickets are exactly this, and the fix (prefetch of 1 or near it) is counterintuitive because everywhere else low prefetch hurts throughput.
The prompt also pushes back on over-engineering the priority levels. Each level carries overhead, and almost no real workload needs more than two or three tiers; the model is steered to map actual traffic onto a small x-max-priority rather than inventing ten unused levels. That keeps the queue cheap and the design honest.
Starvation and the single-queue-versus-separate-queues choice are the architectural judgment calls, and the prompt makes them explicit rather than assuming a priority queue is automatically right. A flood of urgent messages can starve the normal tier forever, which sometimes means weighted separate queues are the better design. The guardrails capture the two facts that bite in production: x-max-priority must be set at declare time and can’t be retrofitted, and priority behavior only reveals itself under realistic load with production prefetch — so the staging load test is the proof, not a quick functional check.