Capabilities
What the KubeMQ RabbitMQ (AMQP 0-9-1) connector supports, negotiates, rejects, enforces or ignores as declare arguments, and its gotchas.
This reference defines exactly what the embedded KubeMQ RabbitMQ (AMQP 0-9-1) connector supports, the values it negotiates, the methods it rejects, the declare arguments it enforces, and the ones it accepts but ignores. Use it to decide which client features are safe to rely on and which ones will be refused. Where a behavior was measured against a real RabbitMQ 4.3.4 broker, the page says so.
Supported AMQP methods
| Class | Methods |
|---|---|
| Connection | connection.start / start-ok / tune / tune-ok / open / open-ok / close / close-ok / blocked / unblocked / update-secret |
| Channel | channel.open / close / flow (active=true replies flow-ok; active=false is refused 540) |
| Exchange | exchange.declare (incl. passive), exchange.delete, exchange.bind, exchange.unbind |
| Queue | queue.declare (incl. passive, server-named), queue.bind, queue.unbind, queue.purge, queue.delete (incl. if-unused / if-empty) |
| Basic | basic.publish, basic.consume, basic.cancel, basic.deliver, basic.get, basic.ack, basic.nack, basic.reject, basic.qos, basic.recover (requeue=true), basic.recover-async (requeue=true), basic.return |
| Confirm | confirm.select (publisher confirms) |
| Tx | tx.select, tx.commit, tx.rollback — RabbitMQ semantics, bounded at 65,536 operations and 128 MiB of bodies per open transaction |
Exchanges and bindings are virtual connector-side routing — every AMQP queue is backed by
a single KubeMQ Queue channel (amqp.{vhost}.{queue}). See
Channel Mapping and
Architecture.
Advertised server capabilities
connection.start advertises all of these as true: publisher_confirms, basic.nack,
consumer_cancel_notify, connection.blocked, authentication_failure_close,
per_consumer_qos, direct_reply_to, exchange_exchange_bindings.
connection.blocked is sent only while the broker is not ready (and connection.unblocked on
recovery) — there is no memory or disk alarm behind it. During that window publishes, consumes
and topology operations are refused 541.
Negotiated values
The connector proposes these during connection.tune. A client may lower channel-max and
frame-max; the heartbeat is the smaller non-zero value of the two sides:
| Value | Default |
|---|---|
| ChannelMax | 2047 (1–65535) |
| FrameMax | 131072 (floor 4096; a configured value above 512 MiB is clamped down with a startup warning) |
| Heartbeat | 60s (server sends every half interval; no traffic for twice the interval → TCP close + client.timeout audit) |
| MaxBodySize | 104857600 (100 MiB); larger → channel.close(406) at the content header |
| MaxConnections | 1000 (0 = unlimited; over the limit the handshake completes, then connection.close(320)) |
| Protocol header | exactly AMQP\x00\x00\x09\x01 (8 bytes); mismatch → the server's header bytes back + TCP close |
See Configuration for the fields behind each.
SASL mechanisms
| Mechanism | Offered |
|---|---|
PLAIN | Always |
AMQPLAIN | Always — the same two credential rules as PLAIN, for older client libraries |
EXTERNAL | Only when Connectors.Amqp.SslCertLogin = true and the listener verified a client certificate under mutual TLS |
ANONYMOUS | Never, in any configuration; selecting it is refused 503. RabbitMQ 4.3.4 advertises it by default |
What the password means, and which subject a policy must name, is in Authentication and Users and permissions.
Not implemented (540)
These always return 540 not-implemented — each exactly as RabbitMQ 4.3.4 answers it:
basic.recover-async(requeue=false)andbasic.recover(requeue=false);basic.qos(prefetch-size != 0)— a byte-based prefetch is refused, not ignored;basic.publish(immediate=true);channel.flow(active=false).
See Error & Reason Codes for the full close-code table.
Exchange types
| Type | Routing |
|---|---|
Default ("") | Implicit binding: routing key = queue name |
direct | Exact routing-key match (multiple queues per key allowed) |
fanout | All bound queues |
topic | Trie matcher: * = exactly one word, # = zero or more words, . separator |
headers | x-match ∈ all / any / all-with-x / any-with-x (default all) |
x-delayed-message | The delayed-message plugin's type. Routes by the x-delayed-type argument (one of the four above); x-delay delays delivery exactly as it does on every other exchange |
Pre-declared per vhost (durable, undeletable, amq. prefix reserved): amq.direct,
amq.fanout, amq.topic, amq.headers, amq.match, and the internal amq.rabbitmq.trace;
the default vhost also carries the internal amq.rabbitmq.log. The two internal exchanges exist
so tooling that declares or binds to them keeps working: a direct publish to either is refused
403, and nothing is ever routed through them (no firehose tracing, no log forwarding).
Enforced declare arguments
These arguments change behavior. Several carry an upgrade hazard, marked in the last column:
| Argument | Where | Effect | Watch out |
|---|---|---|---|
x-dead-letter-exchange, x-dead-letter-routing-key | queue | Dead-lettering on rejected, expired and maxlen with a RabbitMQ-exact x-death array | A dead-letter exchange that routes nowhere drops the message; DeadLetterMaxHops (16) destroys a message that crosses it |
x-message-ttl | queue | Queue-level TTL; the minimum of it and the per-message expiration applies | 0 means "no TTL" here; above Queue.MaxExpirationSeconds on a queue with no DLX is refused 406 |
x-expires | queue | An idle queue (no consumer, no redeclare, no basic.get) is deleted with its messages after the window | Publishing does not count as use; a periodically drained queue is idle in between |
x-max-length + x-overflow | queue | Depth limit with reject-publish or reject-publish-dlx | No x-overflow, or drop-head, is refused at declare 406; the limit is best-effort (2-second cache) |
x-delivery-limit | queue | Poison cap: N deliveries, the (N+1)th diverts to the DLX | Refused unless the DLX resolves to exactly one queue; 0 refused; above Queue.MaxReceiveCount refused |
x-single-active-consumer | queue | One active consumer at a time, takeover in registration order | Held cluster-wide by node presence |
alternate-exchange | exchange | Unroutable messages go to the alternate, chains included | Requires read on the exchange and write on the alternate at declare time |
x-delayed-type | exchange | Selects the routing type of an x-delayed-message exchange | Missing or non-string → 406; naming an unknown type → 503 |
x-priority | basic.consume | Consumer priority; higher consumers with prefetch room receive first | Arbitrated per node; a non-integer is 406 |
x-delay | message header | Delays delivery, on every exchange | Clamped to MaxDelaySeconds; stripped on delivery |
Inert arguments (accepted, badged, no effect)
Accepted, stored in topology metadata, logged once per entity, and badged in the dashboard topology view — but they never alter behavior:
x-max-length-bytes— the queue-depth snapshot carries no byte total;x-queue-type/x-queue-mode— every queue is the one durable, disk-backed type;x-max-priority— thepriorityproperty is carried as a tag, but ordering is not honored.
Do not assume an argument is inert because an older version of this page said so.
x-max-length, x-overflow, x-expires, x-message-ttl, x-delivery-limit,
x-single-active-consumer, consumer x-priority and alternate-exchange were all once listed
here and are all now enforced. x-expires in particular deletes a queue that was safe
before. Audit your declares before upgrading — see deviations 2 and 15 in
Migrating from RabbitMQ.
The gotchas
These connector behaviors deviate from RabbitMQ. Each is a documented contract, not a bug — most stay invisible until a corner case hits production.
| # | Gotcha | Where documented |
|---|---|---|
| 1 | Expiry is eager only on the wait-queue shape — queue-level x-message-ttl + a DLX + no consumer is swept within ceil(candidates / 8) × 30 s; every other shape expires only when a reader reaches it | Reliability |
| 2 | x-max-length without x-overflow is refused — RabbitMQ's default drop-head has no equivalent; declare reject-publish or reject-publish-dlx | Migrating from RabbitMQ |
| 3 | Publisher confirms have no rollback — already-delivered queues stay; retry duplicates | Reliability |
| 4 | basic.get on an empty queue answers in about 50 ms, not RabbitMQ's 1 ms; prefer basic.consume for throughput | Queues & Consumers |
| 5 | Requeue at tail, not head — fairness differs from RabbitMQ classic | Queues & Consumers |
| 6 | Exclusivity is cluster-wide by gossip — a node silent for 20 seconds loses its claims; single-active takeover is by node presence and consumer priorities are per node | RPC pattern, Migrating from RabbitMQ |
| 7 | Inert queue arguments — byte limits, queue type and message priority are accepted but never apply | this page, Exchanges & Routing |
| 8 | Reserved "default" vhost + name charset — ;:*> / whitespace / trailing . rejected; a vhost may not contain . at all | Channel Mapping |
| 9 | Publish-then-close loses unconfirmed messages — a fire-and-forget basic.publish then an immediate close silently drops still-buffered publishes; use a confirm channel before closing | Reliability |
| 10 | x-expires deletes the queue and its messages — publishing does not count as use | Migrating from RabbitMQ |
| 11 | The dead-letter hop ceiling destroys the message — on a retry ladder DeadLetterMaxHops (16) is a cap on retry cycles | Reliability, Configuration |
| 12 | Token expiry closes the connection with 320; refresh with connection.update-secret | Authentication |
| 13 | Configuring users changes the authorization subject to the encoded username — every policy naming the token's client id stops matching | Users and permissions |
| 14 | Every message is persisted regardless of delivery_mode — every queue is disk-backed | Migrating from RabbitMQ |
Related
Channel Mapping
How every AMQP queue maps to amqp.{vhost}.{queue}, the name charset, and property/header mapping.
Error & Reason Codes
The 311–541 close-code table and the triggers behind each rejection above.
Management HTTP API
The RabbitMQ-compatible read-mostly subset on port 15672 and definitions export/import.
Migrating from RabbitMQ
The full deviation list, what never comes, and the connection-string swap.
Was this page helpful?
Work Queues
Distribute time-consuming tasks across competing workers over AMQP 0-9-1 — durable queues, manual ack, prefetch, and at-least-once delivery on the KubeMQ Queue.
Channel Mapping
The reference for how a RabbitMQ AMQP 0-9-1 queue maps to a KubeMQ Queue channel — the amqp.{vhost}.{queue} grammar, charset, and property/header mapping.