MQTT 5 vs MQTT 3.1.1: Differences, Features & Migration

By | June 29, 2026

If you have used MQTT 3.1.1 for a few years and are wondering what MQTT 5 actually changes, or if you are starting a new deployment and need to decide between the two, this is the article that gets you there directly. The two versions share the same core protocol — publish/subscribe over TCP, three QoS levels, retained messages, last will and testament, persistent sessions — but MQTT 5 adds a set of features and behavioral refinements that change how you design, debug, and operate a real system.

This article compares MQTT 5 and MQTT 3.1.1 side by side, feature by feature and behavior by behavior, with side trips into the practical implications of each difference. It is structured for scanning, with comparison tables in every section and decision-oriented summaries at the end. For deep dives on any individual MQTT 5 feature, the dedicated articles in this category go further.

At a glance

AspectMQTT 3.1.1MQTT 5
StandardizedOASIS, October 2014OASIS, March 2019
Wire-level protocol version byte45
Wire compatibilityNot wire-compatible with 3.1.1; brokers can support both side by side
Control packet types1415 (adds AUTH)
Packet propertiesNone — flags onlyYes — typed key-value properties on most packets
User properties (application metadata)NoYes
Reason codes6 (only on CONNACK)20+ across most acknowledgement packets
Reason strings (human-readable)NoYes (optional)
Server-initiated DISCONNECTNoYes, with reason code
Session modelClean Session flagClean Start + Session Expiry Interval
Session lifetimeIndefinite once persistentBounded by Session Expiry Interval
Message expiryNoYes, per-PUBLISH (Message Expiry Interval)
Capability discoveryNoYes (CONNACK properties)
Topic aliasesNoYes (per-connection alias for long topics)
Shared subscriptionsVendor-specific extensions onlyStandardized ($share/<group>/<topic>)
Request/responseAd-hoc patterns in applicationStandardized (Response Topic, Correlation Data)
Flow controlNo protocol-level limitReceive Maximum bounds in-flight QoS 1/2 publishes
Enhanced authenticationNo (username/password only at protocol level)AUTH packet supports challenge/response (SASL, OAuth tokens)
Will DelayNoYes (delay before publishing the will)
Retransmission on healthy connectionAllowedRemoved (retransmit only after reconnect)
Username without passwordRequired if password setPassword may be sent without username

The rest of this article walks through these differences in detail, grouped by what they affect.

Core protocol elements that did not change

Before listing the differences, it is worth stating what stayed the same. MQTT 5 is an evolution, not a rewrite, and any developer fluent in MQTT 3.1.1 already understands most of MQTT 5.

ElementStatus across versions
Publish/subscribe model with broker in the middleUnchanged
Topic structure (UTF-8 hierarchical strings with / separator)Unchanged
Single-level + and multi-level # wildcardsUnchanged
Three QoS levels (0, 1, 2) with the same handshakesUnchanged
Per-hop QoS negotiation and downgradeUnchanged
Retained messages, last known value per topicUnchanged
Last Will and Testament mechanismUnchanged (refined; see below)
Keep alive with PINGREQ and PINGRESPUnchanged
TCP/IP transport, ports 1883/8883, WebSocketsUnchanged
Binary packet format with fixed headerUnchanged

If you know how the pub/sub model, QoS handshakes, retained messages, and keep alive work in MQTT 3.1.1, you know how they work in MQTT 5 too. The new material in MQTT 5 sits on top of this foundation rather than replacing it.

Why the version number jumped from 3.1.1 to 5

A short note worth getting out of the way: there was never an “MQTT 4.” The protocol version is encoded as a single byte in the CONNECT packet. MQTT 3.1 sends value 3 on the wire; MQTT 3.1.1 sends value 4. To make the version name match the wire-level value, the next version uses 5 in both places. The naming is mechanical, not semantic.

Differences in error reporting and diagnostics

This is the area where MQTT 5 most directly improves the day-to-day experience of running MQTT.

CapabilityMQTT 3.1.1MQTT 5
Number of CONNACK return/reason codes620+
Reason codes on PUBACKNoYes
Reason codes on PUBREC, PUBREL, PUBCOMPNoYes
Reason codes on SUBACKOne per topic (success/failure)One per topic with specific reason
Reason codes on UNSUBACKNoYes, one per topic
Reason codes on DISCONNECTNo (no broker-side DISCONNECT exists)Yes, in either direction
Reason string (human diagnostics)NoYes (optional)
Server-initiated DISCONNECT with explanationNo (broker just closes the socket)Yes

The practical effect: in MQTT 3.1.1, failure modes often look identical to the client. A publish that the broker refused, a publish that nobody was subscribed to, and a publish that succeeded all look the same. The broker closing the connection because of a protocol violation looks the same as the network failing. In MQTT 5, the broker can tell the client what happened, with a specific reason code and (optionally) a human-readable string. This is covered in detail in the Improved Client Feedback and Negative Acknowledgements article.

Differences in session management

MQTT 5 replaces MQTT 3.1.1’s single cleanSession flag with a two-control model and adds a session lifetime that the protocol bounds.

CapabilityMQTT 3.1.1MQTT 5
Session persistence flagcleanSession (boolean)Clean Start (boolean)
Session lifetimeIndefinite once cleanSession = falseSet by Session Expiry Interval (seconds)
Session lifetime change at disconnectNot possibleCan update Session Expiry Interval in DISCONNECT
Maximum session lifetimeImplementation-defined (no protocol bound)Up to 4,294,967,295 seconds (about 136 years)
Per-message TTL (Message Expiry)NoYes, set on each PUBLISH

Mapping the old behavior to the new: cleanSession = true in MQTT 3.1.1 maps to Clean Start = true with Session Expiry Interval = 0 in MQTT 5 (start fresh, end with the connection). cleanSession = false in MQTT 3.1.1 maps to Clean Start = false with a large Session Expiry Interval, though in practice the better default in MQTT 5 is to pick a finite lifetime that matches the device’s expected offline pattern rather than the effectively-unbounded maximum. Both mechanisms are covered in the Persistent Sessions and Session and Message Expiry Intervals articles.

Differences in metadata and payload description

This is where MQTT 5’s properties machinery is most visible. MQTT 3.1.1 had no place for application metadata at the protocol level; MQTT 5 adds it.

CapabilityMQTT 3.1.1MQTT 5
User properties (arbitrary key-value)NoYes, on most packet types
Payload format indicator (binary vs. UTF-8)NoYes
Content type (MIME-style)NoYes
Response topic and correlation data (for request/response)No (must be encoded by application)Yes (protocol-defined)
Subscription identifiersNoYes (let subscriber tag its subscriptions)

In MQTT 3.1.1, application metadata had to be encoded into the topic name (turning routing into a description) or into the payload (forcing every consumer to parse an envelope). MQTT 5 gives metadata a designated place where it does not compromise either. The User Properties and Payload Format Description articles cover this in detail.

Differences in scalability features

CapabilityMQTT 3.1.1MQTT 5
Shared subscriptionsVendor-specific extension on some brokersStandardized ($share/<group>/<topic>)
Topic aliases (short integer for long topic)NoYes (per-connection alias)
Capability discovery (what the broker supports)NoYes (CONNACK properties)
Maximum packet size negotiationNoYes (CONNACK Maximum Packet Size)
Flow control (bound in-flight QoS 1/2)No (sender can flood receiver)Yes (Receive Maximum)

Shared subscriptions deserve a specific note: load-balancing message delivery across consumer instances was something users had been doing in MQTT 3.1.1 with vendor-specific broker features (the syntax and behavior varied). MQTT 5 standardized the mechanism, which means a multi-consumer load-balancing setup that works on one MQTT 5 broker will work on another.

Flow control is also a new safety mechanism. In MQTT 3.1.1, there was nothing stopping a publisher from sending thousands of QoS 1 or 2 publishes faster than the broker (or the broker faster than a subscriber) could process them, leading to memory pressure or dropped connections. MQTT 5’s Receive Maximum lets each side bound how many unacknowledged publishes the other may have in flight; if exceeded, the sender gets a clear protocol error rather than mysterious failures. The Flow Control article covers this.

Differences in authentication and security

CapabilityMQTT 3.1.1MQTT 5
Username and password in CONNECTYes (username required if password set)Yes (password may be sent without username)
TLS for transport securityYes (operational, not protocol-level)Yes (operational, not protocol-level)
Multi-step challenge/response authenticationNoYes (new AUTH packet)
Re-authentication during a sessionNoYes (via AUTH packet)
Standard support for SCRAM, Kerberos, OAuth tokensNoYes (via AUTH and SASL mechanisms)

MQTT 3.1.1’s authentication was minimal: send a username and password in CONNECT, succeed or fail. Real-world deployments routinely wanted more (challenge-response with mutual proof, token-based authentication, the ability to re-authenticate without dropping the connection), and built it outside the protocol. MQTT 5’s new AUTH packet supports a full SASL-style multi-step exchange and re-authentication mid-session, covered in the Enhanced Authentication article.

Differences in Last Will and Testament

The LWT mechanism is the same in both versions at its core: a will registered in CONNECT, published by the broker on ungraceful disconnect. MQTT 5 refines it in a few ways.

CapabilityMQTT 3.1.1MQTT 5
Will fields (topic, payload, QoS, retain)YesYes
Will Delay Interval (delay before publishing)NoYes
Will properties (user properties, content type, etc.)NoYes
Will on graceful DISCONNECTAlways suppressedOptionally triggered via reason code 0x04
Will Message Expiry IntervalNoYes

The Will Delay Interval is particularly useful. In MQTT 3.1.1, every brief network glitch that reaches the keep alive timeout causes a will to fire, which is often not what was wanted. In MQTT 5, the broker waits the configured delay before publishing; if the client reconnects within that time, the will is canceled. Covered in the Last Will and Testament article.

Behavioral changes you should know about

Some MQTT 5 changes are not about new features but about how the protocol behaves. These can catch you off guard during migration.

No retransmission on a healthy connection. In MQTT 3.1.1, an unacknowledged QoS 1 or 2 PUBLISH could be retransmitted while the connection was still open, on an implementation-defined timer. In practice this often made things worse: a slow client got hit with duplicate publishes before it had finished processing the original. MQTT 5 removes the requirement for timer-based retransmission during an active TCP connection; retransmission happens only after a reconnect, when unacknowledged packets are sent again as part of resuming the session. Systems that relied on in-connection retransmission need to be reviewed.

Sessions can now expire on their own. A client with cleanSession = false in MQTT 3.1.1 could be confident that its session would persist as long as the broker was running. In MQTT 5, the broker honors the Session Expiry Interval and can discard a session after disconnect even if no one wipes it explicitly. A client that does not return within its session expiry comes back to a fresh session, with session present = false in the CONNACK.

Retransmission is bounded by Receive Maximum. With MQTT 5’s flow control, a sender that tries to publish more unacknowledged QoS 1/2 messages than the other side’s Receive Maximum allows will be disconnected with reason code 0x93 (Receive Maximum Exceeded). MQTT 3.1.1 had no equivalent limit; sending too aggressively in 3.1.1 was often a quality-of-service problem, but did not produce a protocol error.

ClientId conflicts trigger take-over either way. This behavior did not change, but it is worth knowing in both directions: when a new connection arrives with a ClientId already in use, the broker closes the existing connection. This was true in MQTT 3.1.1 and remains true in MQTT 5. The Keep Alive and Client Take-Over article covers this.

Capability advertisements are best read on every connect. A client connecting to a broker for the first time, or after the broker has been reconfigured, may find different capabilities or limits than it expected. MQTT 5 clients should treat the CONNACK as authoritative for capability and limit information on every connect, not just the first.

What the upgrade actually requires

For a deployment to use MQTT 5, three things must change:

  1. The broker must be MQTT 5 capable. Most modern MQTT brokers support MQTT 3.1.1 and MQTT 5 side by side, accepting either on the same port. Verify that the broker version you are running speaks MQTT 5.
  2. Each client must be on a library that supports MQTT 5. The client library is what builds the packets and parses the responses. A client built on an MQTT 3.1.1-only library cannot speak MQTT 5 even if the broker supports it; the library has to know how.
  3. Application code may need to change. Most basic MQTT operations (connect, publish, subscribe, callbacks) work the same way at the API level. Behavioral changes (no in-connection retransmission, session expiry, capability advertisements) and new features (user properties, reason codes, request/response) need application-level handling to be useful.

The good news is that mixed deployments are common and supported. You can run MQTT 5-capable brokers, migrate clients to MQTT 5 in waves as their firmware allows, and have both versions coexisting indefinitely. There is no flag day required.

When to choose each version

For most new deployments today, MQTT 5 is the right default. The improved diagnostics alone justify it for any system that has to be operated by humans rather than autonomously. The new features that matter most depend on the use case.

Choose MQTT 5 if you need any of:

  • Better diagnostics (reason codes, reason strings, server-side DISCONNECT with explanation).
  • Bounded session and message lifetimes (Session Expiry and Message Expiry Intervals).
  • Application-level metadata on messages (user properties, content type, payload format).
  • Load balancing across consumer groups (shared subscriptions).
  • Reduced bandwidth for long topic names (topic aliases).
  • Standardized request/response semantics on top of pub/sub.
  • Modern authentication (SCRAM, Kerberos, OAuth tokens) via the AUTH packet.
  • Protocol-level flow control to bound in-flight publishes.

Choose MQTT 3.1.1 only if any of:

  • You have a large existing population of devices that cannot easily be updated to MQTT 5 clients.
  • A specific component in your toolchain does not yet support MQTT 5 well (some older brokers, libraries, or hosted services lag behind).
  • The MQTT 5 features above genuinely solve no problem in your deployment, and the migration effort is not justified.

The migration cost is real but bounded. Brokers commonly support both versions; library updates are usually straightforward; the behavioral changes can be reviewed against your specific design. For deployments large enough to have problems that MQTT 3.1.1 cannot solve, MQTT 5 is worth the work.

MQTT 3.1.1 patterns to retire on MQTT 5

If you are coming from MQTT 3.1.1, you have probably built application-level workarounds for things MQTT 3.1.1 could not do. Several of those workarounds become obsolete under MQTT 5 and should be retired during migration, because keeping them adds complexity without benefit.

Pattern from MQTT 3.1.1What to use in MQTT 5 instead
Encoding metadata into topic names (version, source, units)User properties on the PUBLISH
Wrapping payloads in a JSON envelope for metadataUser properties plus content type / payload format indicator
Application-level acknowledgement protocols built on extra topicsStandardized request/response with Response Topic and Correlation Data
Heartbeat publishes to detect device livenessLast Will and Testament with the retained-status pattern (the same pattern works in 3.1.1, but in 5 the Will Delay Interval reduces false alarms)
Cron jobs cleaning up stale persistent sessions on the brokerSession Expiry Interval, set per client
Manually purging old retained messages from defunct devicesMessage Expiry Interval on retained publishes
Vendor-specific shared subscription extensionsStandard $share/<group>/<topic> subscriptions
Polling for broker capabilities by trial and errorCONNACK capability advertisements, read on every connect

This is not an exhaustive list, but each of these is a workaround so common in MQTT 3.1.1 deployments that you likely have at least one of them in production code. Identifying which ones MQTT 5 supersedes is one of the highest-value parts of a migration: you do not just gain features, you also get to delete workarounds.

A migration checklist

If you decide to migrate an MQTT 3.1.1 deployment to MQTT 5, the work breaks down roughly as follows.

  1. Upgrade the broker first, with both MQTT 3.1.1 and MQTT 5 enabled. Existing clients continue to connect on 3.1.1 unchanged.
  2. Verify broker behavior under load with realistic client traffic, including the capability advertisements the broker chooses to expose. Configure server-side maximums (Session Expiry, Maximum Packet Size, Receive Maximum) deliberately rather than accepting defaults.
  3. Pick one class of client to migrate first, ideally one whose firmware is easy to update and whose behavior is well understood. Update its library to MQTT 5 and verify it connects, publishes, and subscribes correctly.
  4. Review behavioral changes for that client class. The most important: it will no longer experience in-connection retransmission, and its session lifetime is now governed by the Session Expiry Interval you set rather than being unbounded.
  5. Start using MQTT 5 features incrementally. Read the CONNACK’s capability advertisements. Add reason code handling to acknowledgement processing. Use Session Expiry deliberately. Add user properties only where they earn their place (do not over-tag every message).
  6. Migrate other client classes in waves. There is no need to migrate everything at once; each class can move on its own timeline.
  7. Eventually decommission MQTT 3.1.1 support on the broker, once no clients remain on the old version. This step is optional; many deployments leave both versions enabled permanently.

A note on testing: MQTT 5’s behavioral changes (no in-connection retransmission, session expiry, flow control limits) can surface in ways that MQTT 3.1.1 testing would not have caught. Stress-test new MQTT 5 deployments with realistic disconnect-and-reconnect patterns to make sure the session model matches what the application actually needs.

Frequently asked questions

Is MQTT 5 backward compatible with MQTT 3.1.1?

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, which most modern brokers do. Coexistence is supported indefinitely.

Do I have to migrate from MQTT 3.1.1 to MQTT 5?

No. MQTT 3.1.1 is still an OASIS standard and remains widely deployed. Migration is worthwhile when the new MQTT 5 features solve real problems in your deployment.

What is the single biggest difference?

Structurally, the introduction of packet properties as a generic metadata mechanism, since almost every new feature is implemented as a property. Operationally, the expanded reason codes and reason strings, which make MQTT systems much easier to debug.

Why is there no MQTT 4?

Because the protocol version is encoded as a single byte in the CONNECT packet, and MQTT 3.1.1 already used the value 4 on the wire. MQTT 5 was named to match its wire-level byte value of 5.

Will my MQTT 3.1.1 client work against an MQTT 5 broker?

Almost certainly yes, if the broker supports both versions (most do). The client connects as 3.1.1 and behaves as 3.1.1; it does not magically gain MQTT 5 features.

Should I use MQTT 5 for new IoT projects?

Yes, in most cases. The improved diagnostics, session and message expiry, and the protocol’s capability advertisements are valuable from day one. Use MQTT 3.1.1 only if a specific constraint forces it.

Are shared subscriptions in MQTT 5 the same as the broker-specific extensions I had in MQTT 3.1.1?

The mechanism is similar but now standardized. MQTT 5’s $share/<group>/<topic> is a protocol-defined syntax that works across compliant brokers, where MQTT 3.1.1’s equivalent features were vendor-specific extensions with varying syntax.

Can MQTT 5 messages be smaller than MQTT 3.1.1 messages?

Yes, in some cases. MQTT 5’s topic alias feature lets a long topic name be replaced by a short integer for the duration of a connection, which can reduce bandwidth significantly on systems with long topic names and frequent publishes.

Does MQTT 5 change how QoS works?

The three levels and their semantics are unchanged. What changes is that retransmission during a healthy connection is no longer required (it happens only after reconnect), the acknowledgement packets now carry reason codes, and Receive Maximum bounds the number of unacknowledged QoS 1/2 publishes in flight.

Author: Zakaria El Intissar

I've spent 13 years in power system automation, electrical protection, and SCADA communication, as an automation and industrial computing engineer. ScadaProtocols.com is where I turn what I've learned on site into plain guides and working tools — so other engineers can decode, analyze, and troubleshoot industrial communication protocols without the guesswork.