MQTT 5 is the current version of the protocol. It was ratified as an OASIS standard on 7 March 2019, succeeding MQTT 3.1.1, which had been the standard since 2014. MQTT 5 is not a rewrite. It is an evolution of MQTT 3.1.1 that keeps the core (publish/subscribe, topics, QoS, sessions, retained messages, LWT, keep alive) and adds a substantial set of features aimed at scalability, error reporting, and extensibility for the use cases MQTT had grown into.
This article is the overview that the rest of Volume II builds on. It covers the reasons MQTT 5 exists, the foundational protocol-level changes (properties, reason codes, Clean Start, the AUTH packet, bidirectional DISCONNECT, and others), the major new features in summary form, and the considerations involved in upgrading from MQTT 3.1.1. Each individual feature has its own dedicated article in this category; this one is the map, not the deep dive.
Table of Contents
MQTT 5 at a glance
| Property | Detail |
|---|---|
| Standardized | OASIS Standard, 7 March 2019 |
| Predecessor | MQTT 3.1.1 (October 2014), still widely deployed |
| Relationship to predecessor | Not wire-compatible; coexists where brokers support both |
| Wire-level version byte | 5 (matching the version name) |
| New control packet | AUTH (0xF0) |
| Foundational additions | Packet properties, expanded reason codes, reason strings, Clean Start + Session Expiry, bidirectional DISCONNECT |
| Notable new features | User properties, shared subscriptions, topic aliases, request/response, payload format indicator, flow control, message expiry |
| Compatibility | Most modern brokers support both 3.1.1 and 5 side by side |
Why a new version
By the time MQTT 5 was being designed, MQTT had become one of the most widely deployed IoT messaging protocols, connecting devices in industrial control, connected vehicles, logistics, consumer IoT, and the cloud platforms that store and process all of that data. That adoption surfaced limitations of MQTT 3.1.1 that the protocol had not been designed to handle, and demand for features that practical deployments had been bolting on with proprietary extensions for years.
The OASIS technical committee responsible for MQTT had a balancing act: add capabilities long-term users wanted, but without bloating the protocol or breaking its lightweight character. The committee’s charter listed several explicit goals:
- Enhancements for scalability and large-scale systems, including ways to communicate functional levels, define optional functions, and control resource usage.
- Improved error reporting, so clients can react meaningfully to problems rather than guessing.
- Formalizing common patterns, including capability discovery and request/response.
- Extensibility mechanisms, so the protocol can carry custom metadata without further changes.
- Performance improvements and continued support for small clients.
Several features that sophisticated brokers had already implemented on top of MQTT 3.1.1, such as shared subscriptions and time-to-live for messages and sessions, became part of the official standard with MQTT 5. The protocol caught up with what its users had been doing in practice.
Why “5” and not “4”
The version number jump from 3.1.1 to 5 trips people up. The reason is straightforward and unromantic. The CONNECT packet’s fixed header carries the protocol version as a single byte. On the wire, MQTT 3.1 sends value 3, and MQTT 3.1.1 sends value 4. To make the version name on the page match the version byte on the wire, the new version uses 5 in both places. There was never an “MQTT 4” version of the standard; the value 4 was already in use for MQTT 3.1.1.
MQTT is still MQTT
Before going through what changed, it is worth saying clearly what did not. Everything that defines MQTT 3.1.1 still applies in MQTT 5:
- Lightweight, binary protocol with very low per-packet overhead.
- Publish/subscribe with topic-based filtering and the broker at the centre.
- Topics as UTF-8 hierarchical strings with
+and#wildcards on subscriptions. - Three QoS levels (0, 1, 2) with the same semantics and the same per-hop, per-subscription model.
- Persistent sessions storing subscriptions and in-flight QoS state.
- Retained messages, last known value per topic, delivered to new matching subscribers.
- Last Will and Testament, published by the broker on ungraceful disconnect.
- Keep alive with PINGREQ and PINGRESP detecting half-open connections.
- Transport on TCP/IP, with TLS for security and WebSockets for browsers.
Anyone fluent in MQTT 3.1.1 has the conceptual map already. MQTT 5 builds on top of that map with new tools that did not exist before, and refines a handful of existing behaviors. The packet format changes are not radical; the binary protocol still uses the same fixed-header / variable-header / payload structure, the same level-by-level topic matching, and the same QoS handshakes. The main wire-level differences are the addition of a properties section to most packets, the appearance of reason codes and reason strings on more acknowledgements, and the new AUTH packet type. A developer reading MQTT 5 packet captures will recognize them immediately, and the same client APIs (connect, publish, subscribe, callbacks) carry across versions with minor additions.
Foundational changes
Several changes in MQTT 5 are not “features” so much as new mechanisms that the features are built on. Understanding these first makes everything else easier to follow.
Properties
The single biggest structural addition is packet properties: typed key-value fields that can be attached to most MQTT control packets. Properties are how MQTT 5 implements almost every new feature, much the way HTTP headers carry metadata for HTTP. A CONNECT can carry a Session Expiry Interval property, a Receive Maximum property, an Authentication Method property, and more. A PUBLISH can carry a Message Expiry Interval, a Topic Alias, a Content Type, a Response Topic, user properties, and so on. The set of properties available depends on the packet type.
Properties are a far more flexible mechanism than the rigid CONNECT-flag bits of MQTT 3.1.1. They make it possible to add new behavior without inventing new packet types, and they let implementations include or omit information as needed rather than committing to a fixed packet layout. Every individual feature article in Volume II refers back to specific properties.
Expanded reason codes and reason strings
MQTT 3.1.1 had a tiny vocabulary for telling a client what went wrong: just a few return codes on the CONNACK, and on most other packets either no error indicator at all or a single “failure” code. When something went wrong, the client often had to guess what.
MQTT 5 fixes this in two ways. First, the protocol defines many more reason codes, more than 20 in total, covering specific situations such as “Quota Exceeded,” “Payload Format Invalid,” “Topic Filter Invalid,” “Not Authorized,” “Server Busy,” “Receive Maximum Exceeded,” and many others. Second, reason codes can appear on far more packets: CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, and AUTH. So whenever a broker has something to say about a particular operation, it has a defined code for it.
Reason codes are also accompanied by an optional reason string: a human-readable string for diagnostics, separate from the numeric code. The reason code is what programs branch on; the reason string is for the developer or operator reading logs. Brokers typically let you disable reason strings on production for security reasons (since they may leak details). The improved client feedback article covers this expansion in full.
Clean Start and Session Expiry Interval
MQTT 3.1.1 controlled session persistence with a single flag, cleanSession. It conflated two things: whether to start fresh on this connect, and how long the session should live afterward. In practice this meant a persistent session lived indefinitely on the broker once created, with no protocol-level way to bound it.
MQTT 5 splits this into two fields:
- Clean Start, a boolean in the CONNECT, says whether to discard any existing session on this connect.
- Session Expiry Interval, a number of seconds in a CONNECT property, says how long the broker keeps the session after disconnect.
This gives finer control than the old flag did. A cleanSession = true in MQTT 3 maps to Clean Start = true plus Session Expiry Interval = 0 in MQTT 5 (broker starts fresh and removes the session at disconnect). A cleanSession = false in MQTT 3 maps to Clean Start = false plus a nonzero Session Expiry Interval (broker preserves or creates a session and keeps it for that long after disconnect). In between, you can express things MQTT 3 simply could not, like “keep this session for one hour after disconnect, then discard it.” The persistent sessions article and the session and message expiry article cover this in detail.
Bidirectional DISCONNECT
In MQTT 3.1.1, only the client could send a DISCONNECT. If the broker decided to close the connection (perhaps because the client did something wrong), it just closed the TCP socket with no MQTT-level explanation.
MQTT 5 makes DISCONNECT bidirectional. The broker can now send a DISCONNECT to the client before closing the connection, and that DISCONNECT can carry a reason code and reason string explaining why. This drastically improves diagnostics: instead of seeing the connection simply vanish, the client receives an explicit, structured reason. A broker may withhold the exact reason for security purposes (you do not always want to tell an unauthorized client why it was rejected), but the mechanism is there when transparency is appropriate.
The AUTH packet
MQTT 5 adds one new control packet type: AUTH (with packet type code 0xF0). It is used for enhanced authentication, supporting challenge/response authentication mechanisms such as SCRAM, Kerberos, and other SASL-defined methods, as well as IoT-oriented schemes like OAuth-based token authentication. Unlike the CONNECT/CONNACK exchange, which is a single round trip, an AUTH-based authentication can be a multi-step exchange of AUTH packets between client and broker before the connection is finally accepted with a CONNACK.
The AUTH packet can also be used after the connection is established, to re-authenticate without closing the connection. This is genuinely new functionality; MQTT 3.1.1 had no way to renew authentication mid-session. The enhanced authentication article covers the AUTH packet and the authentication flow in detail.
A new data type: UTF-8 string pair
User-defined properties needed a new way to encode a key-value pair on the wire. MQTT 5 adds the UTF-8 String Pair to the protocol’s data types: a key UTF-8 string followed by a value UTF-8 string. With it, the protocol’s wire-level data types are now Bit, Two Byte Integer, Four Byte Integer, UTF-8 Encoded String, Variable Byte Integer, Binary Data, and UTF-8 String Pair. Most application code never touches these directly; the client library or broker handles encoding and decoding. Knowing the list is useful when reading the spec or debugging packet captures.
Healthy-connection retransmission
A small but consequential behavior change: MQTT 5 removed the requirement for timer-based retransmission during an active TCP connection. In MQTT 3.1.1, an unacknowledged QoS 1 or 2 PUBLISH could be retransmitted while the connection was still healthy, on a timer the spec did not define. In practice this often made things worse, because a slow client got hit with duplicate publishes before it had finished processing the original. MQTT 5 stops this from happening: retransmission resumes only after a reconnect, when unacknowledged packets are sent again as part of resuming the session. The practical effect is fewer duplicates and less wasted bandwidth in normal operation, with the same end-to-end guarantee preserved across actual disconnects. The QoS article covers this and the related Receive Maximum flow control mechanism.
Passwords without usernames
A minor but useful relaxation: MQTT 3.1.1 required a username field whenever a password field was set, which was awkward for token-only authentication patterns (such as some OAuth setups, where the credential is a single token with no separate user identity). MQTT 5 allows the password field to be present without a username. The cleaner answer for token-based authentication is the AUTH packet, but for simple cases this relaxation is enough.
Capability discovery: telling the client what the broker supports
A recurring problem with MQTT 3.1.1 was that not every broker supports every feature. Hosted MQTT services in particular often disable QoS 2, retained messages, persistent sessions, or wildcards as a policy or scaling choice. A client trying to use one of those would get an opaque failure with no real explanation, because the protocol provided no way to ask “what do you support?”
MQTT 5 fixes this by letting the broker advertise its capabilities and limits in the CONNACK, via properties. The capability advertisements include:
| Property | Type | Meaning |
|---|---|---|
| Retain Available | Boolean | Whether retained messages are supported |
| Maximum QoS | Number | Highest QoS the client may use |
| Wildcard Subscription Available | Boolean | Whether + and # are usable |
| Subscription Identifier Available | Boolean | Whether subscription identifiers are supported |
| Shared Subscription Available | Boolean | Whether $share/ subscriptions are supported |
| Maximum Packet Size | Number | Largest packet the broker accepts |
| Server Keep Alive | Number | Keep alive the broker is enforcing for this session |
| Receive Maximum | Number | Maximum unacknowledged QoS 1/2 publishes the broker will accept in flight |
| Topic Alias Maximum | Number | Highest topic alias the client may use |
These let a client adapt at connection time rather than fail later. Clients that ignore the capability advertisements will simply hit errors when they use unsupported features, where MQTT 5 brokers can now tell them clearly which feature was the problem via the reason codes mentioned earlier. The improved client feedback article covers capability discovery in full.
The major new features in brief
The foundational changes above enable a set of new features. Each gets its own article in this category; here is the orientation map, with each feature in a sentence or two.
Session and message expiry intervals. Time-to-live for both sessions and individual messages, automatically bounding broker storage. (See Session and Message Expiry Intervals.)
Improved client feedback and negative acknowledgements. Reason codes on many more packets, reason strings, broker-initiated DISCONNECT with explanation, and the capability advertisements above. (See Improved Client Feedback and Negative Acknowledgements.)
User properties. Arbitrary key-value metadata on most packets, similar to HTTP headers. Lets applications carry custom information without protocol changes. (See User Properties.)
Payload format description. A payload format indicator (binary vs. UTF-8) and a Content Type property, letting messages describe their payload so receivers can process them appropriately. (See Payload Format Description.)
Request/response pattern. Standardized Response Topic and Correlation Data properties for genuine end-to-end acknowledgements on top of pub/sub. (See Request/Response Pattern.)
Topic aliases. Substitute a long topic string with a short integer alias for the duration of a connection, reducing bandwidth on systems with long, frequently-used topics. (See Topic Alias.)
Enhanced authentication. Challenge/response authentication via the AUTH packet, supporting SASL-defined mechanisms such as SCRAM and Kerberos as well as token-based methods. (See Enhanced Authentication.)
Flow control. Receive Maximum lets each side bound how many unacknowledged QoS 1/2 publishes the other may have in flight, preventing senders from overwhelming receivers. (See Flow Control.)
Shared subscriptions. Load balancing on top of pub/sub: subscriptions of the form $share/<group>/<topic> distribute each matching message to one member of the group rather than to all of them.
Subscription options. Per-subscription flags such as No Local (do not deliver a publisher its own publishes), Retain As Published (preserve the retain flag on delivery), and Retain Handling (control whether retained messages are delivered on subscribe).
The first eight have full articles in this category. Shared subscriptions and the finer-grained subscription options are useful additions worth investigating when you reach them.
Why upgrade from MQTT 3.1.1
The case for moving to MQTT 5 lines up with the original objectives but is worth stating concretely.
Better error handling and diagnostics. Reason codes on every acknowledgement, reason strings for humans, broker-initiated DISCONNECT with explanation, and the capability advertisements together change the experience of running and debugging an MQTT system. In MQTT 3, mysterious silent failures and “Connection refused: not authorized” with no further detail are common. In MQTT 5, when something goes wrong, the protocol tells you what.
Resource bounding. Session Expiry Interval and Message Expiry Interval let the protocol bound how long the broker holds state for absent clients and stale messages. In MQTT 3.1.1 these had to be managed at the broker level outside the protocol; in MQTT 5 they are negotiated as part of normal operation.
Application-level metadata. User properties, content type, and payload format indicator give applications a clean place to put metadata that previously had to be encoded into payloads or topic names. This is particularly useful in multi-team or multi-vendor systems, where consistent message structure is hard to enforce at the payload level alone.
Scalability features. Shared subscriptions standardize load balancing across consumer groups, which had been a custom feature in some MQTT 3 brokers. Topic aliases reduce bandwidth on long-topic deployments. Flow control via Receive Maximum lets each side protect itself from being overwhelmed.
Standardized request/response. End-to-end acknowledgement on top of pub/sub is a pattern many systems built themselves on MQTT 3; MQTT 5 makes it part of the protocol.
Modern authentication. The AUTH packet supports the kinds of challenge/response and token authentication that modern security architectures expect.
The cost of upgrading is real but manageable. MQTT 5 is not wire-compatible with MQTT 3.1.1, so brokers and clients have to be running MQTT 5–capable software. Most modern MQTT brokers support MQTT 3.1.1 and MQTT 5 side by side, accepting either on the same port, which allows gradual migration. The protocol’s behavior change around retransmission (no timer-based retransmits during a healthy connection) means systems that relied on that behavior need to be reviewed. The expanded properties mean wire captures and tooling need to know how to parse them. None of these are blockers, but they are real work, especially for production systems with many deployed clients.
How MQTT 5 connects to the rest of this category
This article is the orientation map; the detailed treatment of each feature lives in the articles that follow:
- Session and Message Expiry Intervals — full treatment of the new expiry mechanism for sessions and individual messages.
- Improved Client Feedback and Negative Acknowledgements — reason codes, reason strings, server DISCONNECT, capability advertisements.
- User Properties — the key-value metadata mechanism applied to all packet types.
- Payload Format Description — the format indicator and content type properties.
- Request/Response Pattern — Response Topic, Correlation Data, and the end-to-end acknowledgement pattern.
- Topic Alias — substituting long topic strings with integer aliases per connection.
- Enhanced Authentication — the AUTH packet and SASL-style challenge/response authentication.
- Flow Control — Receive Maximum and bounded in-flight publishes.
The Volume I articles in this category cover the underlying protocol (pub/sub, topics, QoS, sessions, retained messages, LWT, keep alive, connection handshake, WebSockets) that MQTT 5 builds on. None of that material is superseded by MQTT 5; it is the foundation the new features extend.
Frequently asked questions
What is MQTT 5? MQTT 5 is the current version of the MQTT messaging protocol, ratified as an OASIS standard in March 2019. It builds on MQTT 3.1.1 by adding features for scalability, error reporting, extensibility, and modern authentication, while keeping the core pub/sub model unchanged.
Why did the version jump from 3.1.1 to 5? The protocol version is encoded as a single byte in the CONNECT packet. MQTT 3.1.1 sends the value 4 on the wire, so the new version was numbered 5 to match its wire-level byte value. There was never an MQTT 4 standard.
Is MQTT 5 backward compatible with MQTT 3.1.1? No, not at the wire level. An MQTT 3.1.1 client and an MQTT 5 broker can talk only if the broker explicitly supports both versions. Most modern MQTT brokers support MQTT 3.1.1 and MQTT 5 side by side, accepting either on the same port, which allows gradual migration.
What is the biggest change in MQTT 5? Structurally, the introduction of packet properties as a generic metadata mechanism. Most new features are implemented as properties on existing packets. The improved error reporting (reason codes, reason strings, server DISCONNECT) and the capability advertisements in CONNACK are also among the most impactful changes in everyday use.
What is a reason code? A number that explains why a particular operation succeeded or failed. MQTT 5 defines more than 20 reason codes covering specific situations such as Not Authorized, Quota Exceeded, Topic Filter Invalid, Receive Maximum Exceeded, and others. Reason codes can appear on most acknowledgement packets and on DISCONNECT.
What is the difference between Clean Session in MQTT 3 and Clean Start in MQTT 5? MQTT 5 splits the single Clean Session flag into Clean Start (whether to discard any existing session on this connect) and Session Expiry Interval (how long the broker keeps the session after disconnect). This gives finer control, including the ability to set a finite session lifetime.
Should I upgrade to MQTT 5? For new deployments, MQTT 5 is the right default. For existing MQTT 3.1.1 systems, the answer depends on what problems you actually have. A simple decision framework:
Use MQTT 5 if any of the following apply:
- You need better diagnostics, particularly the ability to know exactly why a connection or publish was refused.
- You operate large fleets of clients where stale sessions and queued messages accumulate without protocol-level expiry.
- You want time-bounded sessions or time-bounded messages, via Session Expiry and Message Expiry Intervals.
- You need shared subscriptions to load-balance high-volume topics across consumer groups.
- You want standardized request/response semantics on top of pub/sub.
- You need modern authentication (challenge/response or token-based) via the AUTH packet.
- You want to attach application metadata (user properties, content type) to messages without changing payload formats.
Stay with MQTT 3.1.1 if any of the following apply:
- You have a stable population of legacy devices that cannot easily be updated to MQTT 5–capable clients.
- Your broker or client library ecosystem does not yet support MQTT 5 sufficiently for your use case.
- None of the new features solve a real problem in your current deployment, and the upgrade work is not justified by the benefit.
In practice, many deployments end up running both versions concurrently for an extended period, with new clients using MQTT 5 and older clients continuing on MQTT 3.1.1 against a broker that supports both. There is no requirement to flip everything at once.
