Capabilities
What the KubeMQ MQTT connector advertises to clients — the three forced capabilities, configurable limits, protocol-version support, and session semantics.
This reference lists every capability the KubeMQ MQTT connector advertises to clients — including the values that are forced regardless of configuration — plus its configurable limits, protocol-version support, session semantics, and the limitations you must design around. Use it to decide which MQTT client features are safe to rely on and which ones are refused or silently dropped.
Forced (non-configurable) capabilities
These flags are hardcoded in the connector's CONNACK and cannot be changed at
runtime. They are the three load-bearing capability bits an MQTT 5.0 client reads at
connect time, plus the PUBACK-property rule:
| Capability | Wire value | Effect |
|---|---|---|
RetainAvailable | 0 | Retain is disabled. A retained PUBLISH at runtime is silently dropped (success PUBACK 0x00); a Will-retain=true CONNECT is rejected with CONNACK 0x9A. See the retain gotcha. |
SharedSubAvailable | 1 | Required for $share/<group>/queues/<ch> queue consumption. |
WildcardSubAvailable | 1 | Required for Events wildcard subscriptions (+, #). |
NoInheritedPropertiesOnAck | true | PUBACK never echoes the PUBLISH user properties back to the sender. Every successful QoS 1 PUBACK is property-free. |
Retain is silently dropped (RetainAvailable=0). The connector advertises that retain
is unavailable, but if a client sends a retained PUBLISH anyway, the retain flag is
stripped, the message is dropped, and the PUBACK still succeeds (0x00) — the
sender gets no wire-level indication. The only retain-related error is a Will-retain=true
CONNECT, which is rejected with CONNACK 0x9A. There is no durable subscription support.
Configurable limits and defaults
All values below are tunable via CONNECTORSMQTT_CAPABILITIES_* environment variables (see
Configuration).
| Capability | Default | Min | Max | Notes |
|---|---|---|---|---|
MaximumPacketSize | 4194304 (4 MB) | 1 | — | Maximum PUBLISH payload + header size in bytes. Clients sending larger packets are disconnected. |
ReceiveMaximum | 1024 | 1 | 65535 | Maximum concurrent in-flight QoS 1/2 publishes per client (flow control). |
MaximumInflight | 8192 | 1 | — | Broker-wide in-flight QoS message cap. |
MaximumSessionExpiryInterval | 3600 s | 0 | — | Maximum value clients may request for SessionExpiryInterval. |
MaximumMessageExpiryInterval | 86400 s | 0 | — | Maximum allowed message expiry. RPC publishes only: if MessageExpiryInterval is set on a commands/ or queries/ PUBLISH and is shorter than RpcTimeoutSeconds, the effective RPC timeout becomes min(RpcTimeoutSeconds, MessageExpiryInterval). Does not apply to queue or events publishes. |
MaximumQos | 2 | 0 | 2 | Highest QoS the broker grants. |
MinimumProtocolVersion | 4 (MQTT 3.1.1) | 4 | 5 | MQTT 3.1 (level 3) is rejected at CONNECT. |
MaximumClients | 0 (unlimited) | 0 | — | 0 = unlimited. |
Protocol version support
| Protocol | Level byte | Accepted | Notes |
|---|---|---|---|
| MQTT 5.0 | 0x05 | Yes | Full feature set: user properties, reason codes, shared subscriptions, RPC flow. |
| MQTT 3.1.1 | 0x04 | Yes | No user properties, no RPC, no $share queue consume. |
| MQTT 3.1 | 0x03 | Rejected | CONNECT is refused for an unsupported protocol level. Because a level-3 CONNECT uses the MQTT 3.x CONNACK format, the byte returned is the v3 return code 0x01 ("unacceptable protocol version") — not one of the MQTT 5.0 reason codes. |
MinimumProtocolVersion=4 is the hardcoded floor. Set
CONNECTORSMQTT_CAPABILITIES_MIN_PROTOCOL_VERSION=5 to allow MQTT 5.0 clients only.
Session semantics
Sessions are in-memory and node-local:
| Property | Behavior |
|---|---|
clean_start=false (v5) / clean_session=0 (v3.1.1) | Session is preserved in the node's memory. A reconnect to the same node within SessionExpiryInterval restores subscriptions and queued QoS 1/2 messages without re-subscribing. |
| Reconnect to a different node | Session is lost (not replicated across nodes). |
clean_start=true | Fresh session; no state carried over. |
Restored sessions do not replay historical Events-Store messages — the bridge re-subscribes at start-new-only after reconnect. See the no-replay gotcha.
Transport listeners
| Listener | Default port | URL scheme | Notes |
|---|---|---|---|
| TCP (plain) | 1883 | tcp://host:1883 | Always active when Port is set (default 1883). |
| TLS | 8883 | tls://host:8883 | Active only when Security config is present. TLS min 1.2; mTLS supported. If no TLS material is configured, the listener is silently skipped with a warning. |
| WebSocket | 8083 | ws://host:8083/ | Active when WsPort is set. TLS WebSocket (wss://) when Security config present. |
User properties (MQTT 5.0 only) and KubeMQ tags
MQTT 5.0 user properties map bidirectionally to KubeMQ message tags for Events, Events-Store, and Queues patterns. MQTT 3.1.1 has no user properties.
| Direction | Mapping |
|---|---|
| PUBLISH → KubeMQ | Properties.User entries copied 1:1 into KubeMQ Tags (duplicate keys: last-wins). |
| KubeMQ delivery → MQTT subscriber | KubeMQ Tags copied into Properties.User on the injected PUBLISH. |
Hardcoded caps:
| Cap | Value | Violation result |
|---|---|---|
| Maximum user properties per message | 32 | MQTT 5.0: PUBACK 0x97; MQTT 3.1.1: silent drop + publish.error audit. |
| Maximum total bytes (sum of all key + value lengths) | 4096 bytes | Same as above. |
Limitations
These are the design constraints to plan around — each is a hard property of the connector, not a configuration choice:
| Limitation | Detail |
|---|---|
| No retain | RetainAvailable=0 — retained PUBLISH is dropped; Will-retain CONNECT rejected with 0x9A. |
| No durable subscriptions | Sessions are node-local and in-memory; reconnecting to a different node loses the session. |
| Queues are publish-only over MQTT | queues/<ch> accepts produce; consuming requires $share/<group>/queues/<ch>, which is MQTT 5.0 only (3.1.1 has no shared subscriptions). |
| Commands / Queries are MQTT 5.0 only | RPC uses ResponseTopic + CorrelationData; a 3.1.1 publish to commands//queries/ is silently dropped. MQTT clients can only be RPC requesters — responders run on the gRPC side. |
| Events-Store has no historical replay | MQTT subscriptions always start new-only; messages stored before subscribe are never delivered. |
| Ruby client is the v3.1.1 subset | The mqtt gem speaks MQTT 3.1.1 only — no RPC, no $share queue consume, no user properties. |
Gotcha reference
Gotcha 1: retain is silently dropped at runtime
RetainAvailable=0 is advertised at CONNECT. If a client sends a retained PUBLISH anyway:
- The retain flag is silently stripped.
- The connector then drops the message and audits
publish.errorwith text"retain not supported". - The PUBACK succeeds (
0x00). The sender has no indication the message was dropped. - No retained copy is stored; late subscribers receive nothing.
The only case that yields a CONNACK error is Will-retain=true at CONNECT, which
returns CONNACK 0x9A (retain-not-supported), enforced before the session is established.
Gotcha 2: Events-Store has no historical replay
Events-Store subscriptions over MQTT always start new-only. Unlike the REST/gRPC API (which offers six replay positions), MQTT subscribers receive only messages published after the subscription is established. Messages stored before a client subscribes are never delivered.
Gotcha 3 — $share group name is audit-only; all groups compete in one pool
Standard MQTT brokers deliver a separate copy of each message to each $share group. The
KubeMQ connector does not. All $share subscribers on all groups compete in a single
KubeMQ queue pool: each message is consumed exactly once, regardless of group name. The
group name is recorded in audit and metrics only.
Gotcha 4 — RPC requires MQTT 5.0 and PUBACK is immediate
Publishing to commands/ or queries/ from an MQTT 3.1.1 client is silently dropped
(PUBACK 0x00, no RPC issued). The PUBACK for a valid MQTT 5.0 RPC publish is also sent
immediately, before the response arrives — clients must implement their own
response-wait timeout.
Gotcha 5 — literal . in a topic segment conflates with /
events/a.b/c and events/a/b/c both produce KubeMQ channel a.b.c. Avoid dots inside
path segments. See Topic Grammar.
Gotcha 6 — overlapping wildcard filters deliver multiple copies
Each unique subscribe filter has its own independent bridge entry. A publish matching N active wildcard filters results in N deliveries to the client. There is no cross-entry deduplication.
Related
Topic Grammar
Topic-to-channel mapping, wildcards, shared subscriptions, and RPC topics.
Reason Codes
Every MQTT 5.0 reason code the connector produces and what triggers it.
Connections Endpoint
The connections snapshot endpoint and the three Prometheus metrics.
QoS & Sessions
QoS levels, clean-start vs persistent sessions, and the retain/durability caveats in depth.
Was this page helpful?
TLS and WebSocket
Securing and transporting the KubeMQ MQTT connector — plain TCP on 1883, TLS on 8883, WebSocket on 8083, the URL-scheme selector, mTLS, and disabling listeners.
Configuration
Reference for the KubeMQ MQTT connector config fields, capability fields, forced capabilities, validation rules, and TOML/env/Docker examples.