Headers & Choosing an Exchange
The headers exchange
Section titled “The headers exchange”A headers exchange ignores the routing key entirely and routes on the message’s headers — arbitrary key/value pairs in the message properties. A binding specifies the headers a message must carry to match, plus a special argument x-match:
x-match: all— the message must have every header in the binding (a logical AND).x-match: any— the message must have at least one (a logical OR).
For example, a binding of { format: "pdf", type: "report", x-match: "all" } matches only messages whose headers include both format=pdf and type=report.
flowchart LR
p["publish
headers: {format: pdf, type: report}"] --> x["headers exchange"]
x -->|"x-match: all
format=pdf, type=report"| q1["queue: pdf-reports"]
x -. "x-match: all
format=png" .-> q2["queue: images"] Headers routing is powerful when your criteria are genuinely multi-dimensional and don’t compress neatly into one dotted string. In practice it’s the least used type: a well-designed topic routing key usually expresses the same intent more simply and is faster to match. Reach for headers only when routing truly depends on several independent attributes.
Choosing an exchange type
Section titled “Choosing an exchange type”Most routing decisions come down to a short table. Match what you want to the simplest type that expresses it:
| What you want | Exchange type | How |
|---|---|---|
| One clear destination category per message | direct | Bind by exact routing key |
| Broadcast every message to all subscribers | fanout | Each subscriber binds its own queue |
| Subscribers filter by flexible patterns | topic | Bind with * / # patterns on a dotted key |
| Route on several independent attributes | headers | Bind with header conditions + x-match |
A few rules of thumb:
- Start with the simplest type that works. If a single exact key is enough, use
direct— don’t reach fortopicspeculatively. - Default an event bus to
topic. It subsumes direct and fanout, so you keep room to add finer subscribers without changing producers. - Avoid
headersunless you must. A good dotted routing key almost always beats it on clarity and speed. - Design the routing-key scheme early.
domain.detail.action(likeorder.eu.created) is a convention worth agreeing on before the first producer ships.