Exchanges and Routing
How RabbitMQ exchange types (direct, fanout, topic, headers) work as virtual connector-side routing, resolved at publish time into KubeMQ Queue channels.
In the KubeMQ RabbitMQ connector, exchanges and bindings are virtual connector-side routing
metadata, not data stores. There is no exchange object holding messages — a publish to an
exchange is resolved into a set of target queues at publish time, and each resolved queue is
written to its KubeMQ Queue channel amqp.{vhost}.{queue}. This guide covers the exchange types,
topic wildcards, declare idempotency, and what happens to the routing result.
Every AMQP queue maps to a single KubeMQ Queue channel amqp.{vhost}.{queue}. Exchanges and
bindings exist only to select which queues a publish lands in — they are evaluated by the
connector at publish time, then discarded. See
Architecture.
How a publish routes
The matcher produces a set of target queues, deduplicates it, runs a per-queue authorization check, and then writes the message to each surviving queue's KubeMQ channel.
Exchange types
| Exchange type | Routing semantics | Pre-declared (per vhost) |
|---|---|---|
default ("") | Implicit per-queue binding; routing-key = queue name; a missing queue is unroutable | implicit |
| direct | Exact routing-key match; multiple bindings on the same key all match | amq.direct (durable) |
| fanout | All bound queues; routing key ignored | amq.fanout (durable) |
| topic | Trie matcher; * = exactly one word, # = zero or more words, . = word separator | amq.topic (durable) |
| headers | x-match ∈ any-with-x (default all); x--prefixed headers are excluded from matching | amq.headers / amq.match (durable) |
Pre-declared amq.* exchanges
The amq.direct, amq.fanout, amq.topic, amq.headers, and amq.match exchanges are
pre-declared durable per vhost. They:
- cannot be deleted by a client →
403 access-refused; - cannot be redeclared with different args →
406 precondition-failed; - a client declaring any exchange with an
amq.*prefix →403.
Topic wildcards
The topic matcher uses . as the word separator:
| Token | Matches |
|---|---|
* | exactly one word |
# | zero or more words |
Worked examples:
| Binding pattern | Matches | Does NOT match |
|---|---|---|
stock.*.nyse | stock.ibm.nyse | stock.ibm.us.nyse (two words for *) |
stock.# | stock, stock.a, stock.a.b | stocks.a |
# | any key, including the empty key | — |
*.orange.* | quick.orange.rabbit | lazy.orange.elephant.x |
Bindings and declare idempotency
- Declare idempotency: identical args → ok; any field mismatch (type / durable /
auto-delete / internal / deep-equal arguments) →
406. - Passive declare (
passive=true): exists → ok; missing →404 not-found.
The routing result
- The exchange matcher produces a set of target queues.
- The set is deduplicated — a message matching multiple bindings to the same queue is delivered exactly once.
- A per-queue Casbin Write check runs; denied queues are silently removed +
amqp.publish.deniedaudit — see Authentication. - If the routed set is empty:
mandatory=true→basic.return(312 NO_ROUTE)with the full message content;- otherwise the message is silently dropped.
See Reliability for mandatory / basic.return.
Unsupported / inert routing features
| Feature | Behavior |
|---|---|
Exchange-to-exchange bindings (exchange.bind / exchange.unbind) | 540 not-implemented (capability advertised false). |
alternate-exchange argument | Accepted and stored, but inert — WARN once; badged in the dashboard. |
Inert arguments. Several exchange/queue arguments are accepted (and badged in the dashboard
topology view) but never alter behavior: alternate-exchange, priority queues,
x-max-length / overflow, x-queue-type / mode, single-active-consumer, x-expires, and consumer
x-priority. Don't rely on them. See
Capabilities.
Error quick reference
| Trigger | Code |
|---|---|
Unmatched direct routing key, no mandatory | silent drop |
mandatory=true and unroutable | 312 |
| Redeclare with mismatched args | 406 |
| Passive declare of a missing exchange | 404 |
Client declares an amq.* exchange / deletes a pre-declared exchange | 403 |
exchange.bind / exchange.unbind | 540 |
Related
Queues and consumers
Declaring queues, consuming, ack/nack, and prefetch on the amqp.{vhost}.{queue} channels that routing resolves to.
Reliability
Publisher confirms, mandatory/return, dead-letter exchanges, and the publish-then-close footgun.
Channel mapping
The amqp.{vhost}.{queue} naming grammar and how vhosts, queues, and routing keys map to KubeMQ channels.
Was this page helpful?