# Protocol versions (/connectors/mqtt/concepts/protocol-versions)



The KubeMQ MQTT connector supports &#x2A;*MQTT 3.1.1 (protocol level 4)** and &#x2A;*MQTT 5.0 (protocol
level 5)**. MQTT 5.0 is the default and recommended version — it unlocks RPC, Queue consumption,
User Properties, and richer error reporting. MQTT 3.1.1 is retained for compatibility with existing
clients and tooling. MQTT 3.1 (protocol level 3) is **rejected at connect time**.

<Callout type="info">
  Pick **MQTT 5.0** for any new client. Three KubeMQ capabilities — RPC (Commands/Queries), Queue
  **consume** (`$share`), and User Properties ↔ Tags — exist **only** on MQTT 5.0, because the
  3.1.1 wire format lacks the properties they rely on (`ResponseTopic`, `CorrelationData`,
  `$share` shared subscriptions, user-properties).
</Callout>

## Feature matrix [#feature-matrix]

| Feature                                         | MQTT 3.1.1                  | MQTT 5.0                    | Notes                                                                             |
| ----------------------------------------------- | --------------------------- | --------------------------- | --------------------------------------------------------------------------------- |
| Events publish + subscribe                      | Yes                         | Yes                         |                                                                                   |
| Events-Store publish + subscribe (StartNewOnly) | Yes                         | Yes                         | No historical replay over MQTT on either version                                  |
| Queues **produce** (publish to `queues/<ch>`)   | Yes                         | Yes                         |                                                                                   |
| Queues **consume** (`$share/<g>/queues/<ch>`)   | No — requires 5.0           | Yes                         | Needs QoS ≥ 1; `$share` shared subscriptions are 5.0 only                         |
| RPC Commands (publish to `commands/<ch>`)       | No — silently dropped       | Yes                         | 3.1.1 PUBACK succeeds, but the message is **not** executed                        |
| RPC Queries (publish to `queries/<ch>`)         | No — silently dropped       | Yes                         | Same silent-drop behaviour                                                        |
| User Properties ↔ KubeMQ Tags                   | No                          | Yes                         | The wire format only carries user-properties on 5.0                               |
| Rich PUBACK / SUBACK reason codes               | Limited                     | Yes                         | 3.1.1 PUBACK is a single `0x00` byte; detailed codes (`0x83`, `0x87`, …) need 5.0 |
| `ResponseTopic` and `CorrelationData`           | No                          | Yes                         | Required for RPC                                                                  |
| `clean_session=false` session restore           | Yes                         | Yes (`CleanStart=false`)    | Node-local only                                                                   |
| Will-retain at CONNECT                          | No — CONNACK `0x9A`         | No — CONNACK `0x9A`         | Retain not supported on either version                                            |
| Runtime retain publish                          | Silent drop — PUBACK `0x00` | Silent drop — PUBACK `0x00` | See [QoS and sessions](/connectors/mqtt/concepts/qos-and-sessions)                |
| MQTT 3.1 (level 3)                              | Rejected (CONNACK)          | n/a                         | `MinProtocolVersion=4`                                                            |

## What is MQTT 5.0-only [#what-is-mqtt-50-only]

These capabilities have **no MQTT 3.1.1 equivalent** on this connector:

| 5.0 addition                     | KubeMQ usage                                                                                                      |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `ResponseTopic`                  | RPC reply routing for [Commands](/connectors/mqtt/how-to/commands) and [Queries](/connectors/mqtt/how-to/queries) |
| `CorrelationData`                | RPC response correlation                                                                                          |
| User Properties                  | Bidirectional KubeMQ **Tags** mapping (see [Topic mapping](/connectors/mqtt/concepts/topic-mapping))              |
| Shared subscriptions (`$share/`) | Queue **consume** (see [Queues](/connectors/mqtt/how-to/queues))                                                  |
| Extended reason codes            | Detailed PUBACK / SUBACK / CONNACK errors                                                                         |
| `CleanStart` flag                | Per-connect session control                                                                                       |

### RPC silently drops on 3.1.1 [#rpc-silently-drops-on-311]

<Callout type="warn">
  A **3.1.1** publish to `commands/<ch>` or `queries/<ch>` receives a &#x2A;*success PUBACK (`0x00`)** at
  the wire level, but the message is **silently dropped** — it is never executed, and there is **no
  error visible to the publisher**. The drop exists because MQTT 3.1.1 has no `ResponseTopic` or
  `CorrelationData`, so the connector cannot construct an RPC request. RPC requires MQTT 5.0.
</Callout>

To use RPC you must:

1. Connect with **MQTT 5.0** (`protocolVersion: 5` / `MQTTv5` / `Level5`).
2. Subscribe to your own `$reply/<clientID>/...` topic **before** publishing.
3. Set `Properties.ResponseTopic` and `Properties.CorrelationData` on every RPC publish.

## The MQTT 3.1.1 subset [#the-mqtt-311-subset]

MQTT 3.1.1 clients can use:

* Events publish and subscribe (including wildcards)
* Events-Store publish and subscribe (StartNewOnly)
* Queues **produce**
* TLS and WebSocket transports
* Password-as-JWT authentication

They **cannot** use:

| Feature                       | Reason                                                                |
| ----------------------------- | --------------------------------------------------------------------- |
| RPC (Commands / Queries)      | No `ResponseTopic` / `CorrelationData` — silently dropped             |
| Queues consume via `$share`   | `$share` shared subscriptions require 5.0 support in the client stack |
| User Properties ↔ KubeMQ Tags | The 3.1.1 wire format has no user-properties field                    |
| Extended reason codes         | 3.1.1 PUBACK is a bare `0x00` success byte                            |

## MQTT 3.1 is rejected [#mqtt-31-is-rejected]

Protocol level 3 (MQTT 3.1, the original 2010 spec) is **explicitly rejected** — connecting with
protocol level 3 returns a refused CONNACK. The minimum accepted version is &#x2A;*level 4 (3.1.1)**,
controlled by `CONNECTORSMQTT_CAPABILITIES_MIN_PROTOCOL_VERSION=4` (the default).

## Choosing a version per client library [#choosing-a-version-per-client-library]

Most client libraries default to 3.1.1 and require an explicit flag to negotiate 5.0:

<Tabs groupId="language" items="['Go','Python','JavaScript']">
  <Tab value="Go">
    ```go
    // paho.golang's autopaho speaks MQTT 5.0; paho.mqtt.golang speaks 3.1.1.
    // Choosing the v5 client library is how you select the protocol version.
    conn, err := autopaho.NewConnection(ctx, autopaho.ClientConfig{
        BrokerUrls: []*url.URL{brokerURL},
        KeepAlive:  30,
        // ... MQTT 5.0 connection ...
    })
    ```
  </Tab>

  <Tab value="Python">
    ```python
    # paho-mqtt — select the version on the client constructor.
    import paho.mqtt.client as mqtt
    from paho.mqtt.enums import CallbackAPIVersion

    client = mqtt.Client(
        callback_api_version=CallbackAPIVersion.VERSION2,
        protocol=mqtt.MQTTv5,   # use mqtt.MQTTv311 for the 3.1.1 subset
    )
    ```
  </Tab>

  <Tab value="JavaScript">
    ```typescript
    // mqtt.js — protocolVersion: 5 negotiates MQTT 5.0 (omit / 4 for 3.1.1).
    import * as mqtt from "mqtt";

    const client = mqtt.connect("tcp://broker:1883", {
      protocolVersion: 5,
      clientId: "my-client",
      clean: true,
    });
    ```
  </Tab>
</Tabs>

<Callout type="info">
  The Ruby `mqtt` gem is **MQTT 3.1.1 only** and cannot negotiate 5.0, so it ships the documented
  3.1.1 subset (no RPC, no `$share` consume, no User Properties). For 5.0-only patterns from Ruby,
  use a different language or client library.
</Callout>

## Related [#related]

<Cards>
  <Card title="QoS and sessions" href="/connectors/mqtt/concepts/qos-and-sessions" description="QoS 0/1/2, session restore, retain-dropped, and the QoS levels each pattern requires." />

  <Card title="Topic mapping" href="/connectors/mqtt/concepts/topic-mapping" description="The prefix grammar, $share Queue consume, $reply RPC namespace, and User Properties ↔ Tags." />

  <Card title="Reason codes" href="/connectors/mqtt/reference/reason-codes" description="The full PUBACK / SUBACK / CONNACK reason-code table, including the 5.0-only detailed codes." />
</Cards>
