RabbitMQ Exchange & Routing-Key Topology Design Prompt
Design a clean exchange, binding, and routing-key topology for a new or messy RabbitMQ messaging layer so producers and consumers stay decoupled and routing is predictable.
- Target user
- Platform and backend engineers designing AMQP messaging topologies
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior platform engineer who has designed AMQP topologies that survived years of new producers and consumers without a rewrite. Help me design (or untangle) my RabbitMQ exchange and routing topology. I will provide: - The events/messages my producers emit and what each consumer needs to receive - Current topology if any: `rabbitmqadmin list exchanges`, `list bindings`, `list queues` output [PASTE OUTPUT] - Constraints: durability needs, multi-tenant or per-service isolation, expected throughput [DESCRIBE] - Any current pain (messages going to the wrong queue, fan-out duplication, unroutable drops) [DESCRIBE] Your job: 1. **Pick exchange types per flow** — for each message flow, choose direct, topic, fanout, or headers and justify it. Call out where a topic exchange with a structured routing-key hierarchy (e.g. `service.entity.event`) beats a sprawl of direct bindings. 2. **Define the routing-key convention** — propose a consistent, hierarchical routing-key scheme and binding patterns (`*` vs `#`), and show how a new consumer subscribes without producers changing. 3. **Design queues and bindings** — map which queues bind to which exchange with which keys; mark durable vs transient, and flag where an alternate exchange should catch unroutable messages instead of silently dropping them. 4. **Avoid common traps** — fan-out duplication, overly broad `#` bindings, exchange-to-exchange bindings that obscure routing, and tight producer/consumer coupling. 5. **Provide declaration code** — emit idempotent topology declaration (exchange/queue/binding declares) so the topology is reproducible from code, not hand-clicked in the management UI. Output as: (a) a topology diagram in text (exchange -> binding key -> queue), (b) the routing-key naming convention, (c) idempotent declaration snippet, (d) a migration note if changing an existing live topology. Validate the proposed topology on a staging broker first. Re-declaring an exchange or queue with different arguments fails with a PRECONDITION_FAILED; never delete a live exchange or queue on prod to "fix" arguments without reviewing what is bound to it and what messages are in flight.
Why this prompt works
Routing topology is the part of RabbitMQ that quietly decides whether your system stays decoupled or turns into a web of point-to-point bindings nobody understands. The prompt forces a deliberate choice of exchange type per flow rather than defaulting to direct everywhere, and it pushes a hierarchical routing-key convention so a topic exchange can absorb new consumers without producers ever changing. That producer/consumer decoupling is the whole reason to use an exchange instead of publishing straight to a queue.
It also surfaces the failure modes that bite teams in production: unroutable messages silently dropped because no alternate exchange exists, fan-out duplication from sloppy # bindings, and the PRECONDITION_FAILED wall you hit when you try to redeclare a live exchange with different arguments. By asking for idempotent declaration code, the topology becomes reproducible infrastructure rather than something clicked together in the management UI and impossible to rebuild.
The guardrails matter because topology changes on a live broker are destructive in non-obvious ways. Deleting an exchange orphans its bindings; deleting a queue throws away buffered messages. Validating on staging and planning a rename-and-migrate path instead of a forced redeclare keeps a design change from becoming an outage.