# Capabilities (/connectors/amqp/reference/capabilities)



This reference defines exactly what the embedded KubeMQ AMQP 1.0 connector **supports**,
what it **rejects**, and — critically — what it **does not advertise**. Use it to decide
which client features are safe to rely on and which ones will be refused at attach,
transfer, or connection time.

## The connector advertises no capabilities [#the-connector-advertises-no-capabilities]

<Callout type="warn">
  **The connector advertises no offered or desired connection capabilities and no offered or
  desired link/terminus capabilities.** There is &#x2A;*no `ANONYMOUS-RELAY`**, no `queue`/`topic`
  node capability, no `DELAYED_DELIVERY`, no `SHARED-SUBS`, no `sole-connection-for-container`
  — nothing. Clients **must not** depend on AMQP capability negotiation with this connector.
</Callout>

The connector's reply OPEN performative sets **only four fields** — `ContainerID`,
`MaxFrameSize`, `ChannelMax`, and `IdleTimeout`:

```go
serverOpen := &frames.PerformOpen{
    ContainerID:  "KubeMQ",
    MaxFrameSize: c.maxFrameSize,
    ChannelMax:   c.channelMax,
    IdleTimeout:  advertisedIdle,
}
```

`OfferedCapabilities` and `DesiredCapabilities` are **never set** on the OPEN reply, and
the attach-reply path likewise sets no terminus capabilities. The connector *reads* a
peer's terminus capabilities only to honor a bare-address `queue`/`topic` hint — it never
echoes or offers capabilities back.

### What this means in practice [#what-this-means-in-practice]

* **Anonymous senders work, but not via `ANONYMOUS-RELAY`.** A client gets anonymous
  routing by attaching a sender link with a **null target address**; the connector then
  routes each transfer by its `properties.to`. It is **null-target-driven**, not
  capability-driven.
* **This is the root cause of the Java / Qpid JMS anonymous-terminus limitation.** Qpid
  JMS decides whether to use a single anonymous producer link by checking the peer's
  offered `ANONYMOUS-RELAY` capability. Because the connector offers none, Qpid JMS falls
  back to **per-destination sender links** and exposes no API to force the raw null-target
  ATTACH the connector routes on. Native clients (`Azure/go-amqp`, AMQPNetLite,
  qpid-proton, fe2o3-amqp, rhea) can open a null-target sender directly and use anonymous
  routing. See [Address Mapping](/connectors/amqp/reference/address-mapping).
* Do **not** branch your client logic on a negotiated capability — there will be none.
  Drive behavior from the address (`<pattern>/<channel>`) and link-properties instead.

## Supported features [#supported-features]

| Feature                                                          | Support | Notes                                                                                              |
| ---------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| Message body `Data` (binary)                                     | Yes     | the primary body section                                                                           |
| Message body `AmqpValue`                                         | Yes     | string / map / list / scalar values                                                                |
| Empty body                                                       | Yes     | accepted                                                                                           |
| Settlement `accepted` / `released` / `modified` / `rejected`     | Yes     | mapped to KubeMQ Ack/NAck; `released`/`modified` requeue and **increment receive-count**           |
| Sender settle-mode `unsettled` (at-least-once)                   | Yes     | the default; the queues durability path                                                            |
| Sender settle-mode `settled` (pre-settled, at-most-once)         | Yes     | paired with `rcv-settle-mode=first`                                                                |
| Receiver settle-mode `first`                                     | Yes     | the **only** supported receiver settle mode                                                        |
| Link credit + drain (FLOW)                                       | Yes     | manual or windowed credit; drain to exhaust-then-stop                                              |
| Multi-frame transfers (fragmentation/reassembly)                 | Yes     | `More:true…More:false`; bit-exact reassembly up to the 100 MiB cap                                 |
| Dynamic nodes (`dynamic=true`, null address)                     | Yes     | minted `_amqp10.tmp.<connID>.<uuid>`; node-local, no TTL/persistence                               |
| Anonymous terminus (null target, route by `to`)                  | Yes     | per-message Write authz; **not** `ANONYMOUS-RELAY`                                                 |
| JMS/SQL-92 selector on `events/` & `events-store/` consume links | Yes     | `apache.org:selector-filter:string` (3-valued logic)                                               |
| Consumer groups (`x-opt-kubemq-group`)                           | Yes     | link property on the consume link                                                                  |
| Durable subscriptions (events-store, expiry `never`)             | Yes     | durable identity = stable container-id + link name; **node-local**                                 |
| Start positions (`x-opt-kubemq-start`)                           | Yes     | `first` / `new-only` / `last` / `sequence:<n>` / `time:<RFC3339\|unix-secs>` / `time-delta:<secs>` |
| Native RPC (commands / queries)                                  | Yes     | dynamic reply node + `reply-to` + `correlation-id`; **no gRPC, no KubeMQ SDK**                     |
| SASL `ANONYMOUS` / `PLAIN` (JWT) / `EXTERNAL` (mTLS)             | Yes     | see [Authentication](/connectors/amqp/how-to/authentication)                                       |
| TLS / mTLS on `amqps://:5671`                                    | Yes     | see [TLS & mTLS](/connectors/amqp/how-to/tls-and-mtls)                                             |

## Rejected / unsupported features [#rejected--unsupported-features]

These are **non-goals** — they are refused deterministically, not silently ignored. Each
maps to a wire condition from the [error conditions](/connectors/amqp/reference/error-conditions).

| Feature                                                    | Behavior         | Condition / mechanism                                    |
| ---------------------------------------------------------- | ---------------- | -------------------------------------------------------- |
| `rcv-settle-mode=second`                                   | DETACH at attach | `amqp:not-implemented`                                   |
| Selector on a `queues/` link                               | DETACH at attach | `amqp:not-implemented` (queues are move-only)            |
| `copy` distribution-mode on `queues/`                      | DETACH at attach | `amqp:invalid-field`                                     |
| `AmqpSequence` body section                                | rejected         | `errAMQPSequenceUnsupported`                             |
| AMQP **transactions** (txn coordinator)                    | not implemented  | no coordinator node in the connector                     |
| **Exactly-once** delivery                                  | not provided     | at-least-once (queues) or at-most-once (events) only     |
| **Link resumption** / delivery-state recovery on re-attach | not supported    | re-attach is a fresh link                                |
| Message **peek / browse / FIFO ordering guarantee**        | not provided     | competing-consumer move semantics only                   |
| **Dead-letter exchange (DLX)**                             | none             | the broker's `MaxReceiveQueue` caps backlog; no DLX      |
| Second live attach of the same durable identity            | DETACH           | `amqp:not-allowed` (durable subscription in use)         |
| Receiver attach on `responses/<id>`                        | DETACH           | `amqp:not-allowed`                                       |
| AMQP-over-**WebSocket**                                    | not supported    | raw TCP / TLS only                                       |
| **vhost** / virtual host                                   | none             | OPEN `hostname` accepted but ignored; flat address space |
| Config **hot-reload**                                      | not supported    | connector config is read at start                        |
| Capability negotiation (offered/desired)                   | none advertised  | drive behavior from address + link-props                 |

<Callout type="warn">
  The &#x2A;*`AmqpSequence` body section is rejected.** Send `Data` (binary / `BytesMessage`) or
  `AmqpValue` (text / object) instead — an `AmqpSequence` body fails translation. This is one
  of two Qpid-JMS-relevant limitations, alongside the anonymous-terminus restriction in
  [Address Mapping](/connectors/amqp/reference/address-mapping).
</Callout>

## Inert / accepted-but-ignored [#inert--accepted-but-ignored]

These are accepted on the wire without error but carry **no connector semantics**
(documented so you do not expect behavior that is not there):

* **Message priority** — accepted, not honored for ordering.
* **`group-id` / `group-sequence`** — accepted, not used for grouping/ordering.
* **`footer` section** — accepted, passed through where applicable, not interpreted.
* **OPEN `hostname`** — accepted, ignored (no vhost).
* **Idle-timeout from the client** — honored by the connector emitting empty frames at
  half the client's advertised interval, but it is not a feature you negotiate via
  capabilities.

## Limits & forced caps [#limits--forced-caps]

| Limit                            | Value                      | Enforcement / condition                      |
| -------------------------------- | -------------------------- | -------------------------------------------- |
| Max channel length               | 255 bytes                  | charset validation → `amqp:not-found`        |
| Max multi-frame message size     | 100 MiB                    | oversize → `amqp:link:message-size-exceeded` |
| Receiver settle modes            | `first` only               | `second` → `amqp:not-implemented`            |
| Connection / session / link caps | from config                | over-cap → `amqp:resource-limit-exceeded`    |
| Durable identity components      | 40 chars each + FNV suffix | sanitized to a stable durable id             |

See [Configuration](/connectors/amqp/concepts/configuration) for the `CONNECTORS_AMQP10_*`
knobs behind these caps, and
[Connections & Observability](/connectors/amqp/reference/connections-endpoint) for
the metrics that count limit breaches.

## Related [#related]

<Cards>
  <Card title="Address Mapping" href="/connectors/amqp/reference/address-mapping" description="Address grammar, longest-prefix rules, channel charset, and anonymous routing." />

  <Card title="Error Conditions" href="/connectors/amqp/reference/error-conditions" description="The 13 amqp:* conditions that back each rejection above." />

  <Card title="Connections & Observability" href="/connectors/amqp/reference/connections-endpoint" description="The metrics and detail endpoints that count the limit breaches." />

  <Card title="Reliability" href="/connectors/amqp/how-to/reliability" description="Settlement, redelivery, and receive-count semantics in depth." />
</Cards>
