# Channel Mapping (/connectors/rabbitmq/reference/channel-mapping)



This is the master reference for how the embedded KubeMQ RabbitMQ (AMQP 0-9-1) connector maps
an AMQP **queue** to a KubeMQ **Queue** channel. Every AMQP queue — regardless of which
exchange or routing key delivered to it — is backed by exactly one KubeMQ Queue channel.
Exchanges and bindings are **virtual** connector-side routing; the queue is the only durable
object.

<Callout type="info">
  **Everything is a Queue.** The connector mirrors AMQP routing *concepts* (direct / fanout /
  topic / headers exchanges, bindings, RPC) on top of the single KubeMQ **Queue** primitive.
  See [Architecture](/connectors/rabbitmq/concepts/architecture) for the virtual-routing model.
</Callout>

## Grammar [#grammar]

Every AMQP queue maps to exactly one KubeMQ Queue channel:

```text
amqp.{vhost}.{queue}
└┬─┘ └──┬──┘ └──┬──┘
 │      │       └─ the AMQP queue name
 │      └─ the vhost segment (AMQP "/" → DefaultVhost, literal "default")
 └─ fixed connector prefix
```

The mapping is `mappedChannelPrefix + vhost + "." + queue`.

| AMQP queue | Vhost         | KubeMQ channel         |
| ---------- | ------------- | ---------------------- |
| `orders`   | `/` (default) | `amqp.default.orders`  |
| `hello`    | `/`           | `amqp.default.hello`   |
| `probe.q`  | `/`           | `amqp.default.probe.q` |
| `jobs`     | `workers`     | `amqp.workers.jobs`    |

## Constraints [#constraints]

| Constraint         | Rule                                                                                       | Violation                                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| **Length**         | Max 255 chars (prefix + vhost + queue).                                                    | `406 precondition-failed` at queue declaration.                                                                          |
| **Charset**        | Queue/vhost names must NOT contain `;`, `:`, `*`, `>`, whitespace, or end with `.`.        | `406` (queue) / `402` (vhost).                                                                                           |
| **Reserved vhost** | The literal `"default"` vhost is reserved and cannot be client-created — reach it via `/`. | `402 invalid-path` (connector source); a running broker may surface `403 "no access to this vhost"` on a direct connect. |

<Callout type="warn">
  **Reserved `default` vhost + name charset (gotcha #8).** Connect to vhost `/` (which maps to
  the `default` segment); connecting directly to a vhost literally named `default` is rejected
  (`402 invalid-path` per the connector source; a running broker may surface
  `403 "no access to this vhost"`). Names containing `;`, `:`, `*`, `>`, whitespace, or a
  trailing `.` are rejected. See
  [Migrating from RabbitMQ](/connectors/rabbitmq/reference/migration-from-rabbitmq) for the
  rename-before-migration checklist.
</Callout>

## Cross-protocol interoperability [#cross-protocol-interoperability]

Because the backing store is a normal KubeMQ Queue channel, a message published over AMQP to
`amqp.default.orders` is consumable by a gRPC/REST queue client on the same channel, and
vice-versa. The AMQP queue and the KubeMQ Queue channel are the same object viewed through two
protocols.

## Property / header ⇄ tag / metadata mapping [#property--header--tag--metadata-mapping]

### AMQP basic properties → KubeMQ tags [#amqp-basic-properties--kubemq-tags]

Tag namespace `amqp.*`. An absent property produces no tag.

| AMQP property       | KubeMQ Tag                          | Notes                                               |
| ------------------- | ----------------------------------- | --------------------------------------------------- |
| content-type        | `amqp.content-type`                 |                                                     |
| content-encoding    | `amqp.content-encoding`             |                                                     |
| delivery-mode       | `amqp.delivery-mode`                |                                                     |
| priority            | `amqp.priority`                     | carried as a tag; priority ordering itself is inert |
| correlation-id      | `amqp.correlation-id`               |                                                     |
| reply-to            | `amqp.reply-to`                     | rewritten for direct-reply-to                       |
| expiration          | `amqp.expiration`                   | also → `Policy.ExpirationSeconds`                   |
| message-id          | `amqp.message-id`                   | UUID minted if absent                               |
| timestamp           | `amqp.timestamp`                    | Unix seconds                                        |
| type                | `amqp.type`                         |                                                     |
| user-id             | `amqp.user-id`                      | validated vs ClientID when auth enabled             |
| app-id              | `amqp.app-id`                       |                                                     |
| *(routing context)* | `amqp.exchange`, `amqp.routing-key` | **always set on delivery**                          |

### AMQP headers ⇄ KubeMQ metadata [#amqp-headers--kubemq-metadata]

| Direction         | Behavior                                                                                                                                                                                                                                                |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AMQP → KubeMQ** | Headers are wrapped as `Metadata = {"amqp_headers":{...}}` (`metadataEnvelopeKey = "amqp_headers"`). **Always** set, even for nil/empty headers (`{"amqp_headers":{}}`). E.g. header `trace=abc-123` → metadata `{"amqp_headers":{"trace":"abc-123"}}`. |
| **KubeMQ → AMQP** | Native (non-enveloped) gRPC metadata surfaces as the AMQP header `x-kubemq-metadata` (`headerKubemqMetadata = "x-kubemq-metadata"`). E.g. gRPC `metadata="native-metadata"` → AMQP delivery header `x-kubemq-metadata: native-metadata`.                |

Special headers:

* `x-delay` → `Policy.DelaySeconds` (stripped on delivery);
* `x-death` trail reconstructed for dead-lettering;
* `expiration` moved to `x-death[0].original-expiration` when dead-lettered.

<Callout type="info">
  The `{"amqp_headers":{...}}` envelope is what a **gRPC/REST** consumer sees; a pure
  AMQP→AMQP round-trip surfaces headers natively. Treat the envelope as an **interop concern**,
  not a default-path surprise.
</Callout>

## Related [#related]

<Cards>
  <Card title="Architecture" href="/connectors/rabbitmq/concepts/architecture" description="The everything-is-a-Queue model and how virtual exchanges and bindings route into channels." />

  <Card title="Getting Started" href="/connectors/rabbitmq/tutorials/getting-started" description="Connect, declare a queue, and watch vhost / → amqp.default.* in a few steps." />

  <Card title="Capabilities" href="/connectors/rabbitmq/reference/capabilities" description="Supported methods, forced caps, inert arguments, and the nine gotchas." />

  <Card title="Migrating from RabbitMQ" href="/connectors/rabbitmq/reference/migration-from-rabbitmq" description="Rename-before-migration items for the reserved default vhost and the name charset." />
</Cards>
