MQTT Retained Messages Explained: Late Subscribers Guide

MQTT Retained Messages Explained: Late Subscribers Guide

MQTT Retained Messages Explained: Late Subscribers Guide

MQTT Retained Messages Explained: Late Subscribers Guide

What happens when a sensor publishes its temperature reading before anyone is listening? In most messaging systems, that message simply vanishes. In MQTT, it can stick around, waiting for the next subscriber to show up. That behavior comes from retained messages, one of the smallest features in the protocol and one of the most misunderstood. (MQTT: The Standard for IoT Messaging)

This guide breaks down what retained messages actually do, where they help, where they cause trouble, and how to use them without leaving stale data scattered across your broker.

What Is a Retained Message in MQTT?

A retained message is a standard MQTT PUBLISH packet with the RETAIN flag set to 1. When the broker receives it, it stores that message for the topic. Any client that subscribes to a matching topic later receives the stored message immediately, without waiting for the next live update.

The key detail is that the broker keeps only the most recent retained message per topic. A new retained publish replaces the old one. There is no history, no queue, and no replay of past values. Just one current snapshot per topic.

This differs from a normal publish. A regular message goes only to clients connected at that moment. A retained message becomes a persistent piece of state tied to a topic name.

Why Retained Messages Exist

Why Retained Messages Exist

Picture a temperature sensor that publishes every 30 seconds. A dashboard connects, subscribes, and then sits blank for up to half a minute before the first reading arrives. That delay is annoying in a demo and unacceptable in a control room.

Retained messages solve this. When the dashboard subscribes, the broker hands over the last known value instantly. The user sees current state right away, then receives live updates as they arrive.

The same logic applies to device status topics. A light switch publishes “ON” once when toggled. Without retention, a monitoring app that connects an hour later has no idea whether the light is on or off until someone flips it again. With retention, the state is simply there.

How the Broker Handles Retained Messages

The flow is straightforward, but a few rules matter in practice.

  • A publisher sends a PUBLISH packet with RETAIN set to 1.

  • The broker stores the message payload against the topic, replacing any previous retained message for that topic.

  • A new subscriber sends SUBSCRIBE for a matching topic filter.

  • The broker delivers the stored message with the RETAIN flag set to 1, signaling that this is retained data, not a live event.

  • Future live publishes flow normally to all current subscribers.

That fourth step is worth highlighting. Clients can inspect the RETAIN flag on incoming messages to distinguish a stored snapshot from a fresh event. Many libraries expose this as a simple boolean, and good application code uses it to decide whether to update a display or trigger an alert.

Wildcards and Multiple Retained Messages

A subscription using wildcards, such as `home/+/temperature`, can match many topics. In that case, the broker sends one retained message per matching topic at subscribe time. Subscribe to `home/#` on a broker holding fifty retained topics and you will receive fifty messages in a burst.

This is a common source of surprise. Teams test with two topics, then deploy to a broker with hundreds of retained entries and wonder why their client chokes on connect. Plan for the burst.

Clearing a Retained Message

To delete a retained message, publish a zero-byte payload with RETAIN set to 1 to that topic. The broker removes the stored message and does not keep the empty publish. This is the standard cleanup method.

A frequent mistake: developers publish an empty string or a JSON null instead of a truly zero-length payload. The broker then stores that as the retained value, and subscribers receive a useless message forever after. Check the payload length rather than the content alone.

Retained Messages vs. Other MQTT Features

Retained messages are often confused with other persistence mechanisms. They are not the same thing.

Feature What it does Persists after disconnect? Delivers to late subscribers?
Retained message Stores last value per topic Yes, on the broker Yes, on subscribe
Normal publish Delivers to current subscribers only No No
Persistent session (clean session false) Queues messages for an offline client Yes, per client Yes, for that client’s queue
Last Will and Testament Publishes when a client disconnects unexpectedly No Only if retained flag is set

The distinction between retained messages and persistent sessions trips up many teams. A persistent session queues messages for one specific client while it is offline. A retained message is global to the topic and goes to anyone who subscribes. They solve different problems and are often used together.

A Last Will message becomes far more useful when published with the retain flag. A device that drops offline triggers its will, and the retained status topic flips to “offline” for every future subscriber. That pattern is standard in device monitoring, and it pairs naturally with broader cloud infrastructure decisions, where messaging architecture choices shape overall system design. (Apple private cloud compute Google cloud 2026: Explained)

Practical Use Cases That Work Well

Retained messages shine in a handful of scenarios.

Device state and status. A thermostat’s current mode, a door sensor’s open or closed state, a network device’s online status. These are single values that describe “now,” which is exactly what retention handles.

Configuration and discovery. Home Assistant, for example, uses retained MQTT messages for device discovery. A device publishes a retained configuration message describing its entities, and the hub picks it up whenever it starts. This lets devices and hubs boot in any order without coordination.

Last known sensor readings. A pressure sensor in a remote pump station publishes once a minute. Retained messages mean an operator opening the dashboard always sees the latest reading, even if they connect between publishes.

Feature flags and setpoints. A retained message on `plant/line2/setpoint` lets every new subscriber learn the current target value immediately, rather than waiting for the next change.

Where Retained Messages Go Wrong

The feature is simple; the failure modes are not. Here are the ones that show up most often. (Zuckerberg Chan CZI Biohub AI Biomedical Shift 2026: Explained)

Stale Data That Never Expires

MQTT has no built-in expiry for retained messages in version 3.1.1. If a sensor dies, its last retained reading sits on the broker indefinitely. A dashboard may show a temperature from three weeks ago as if it were current.

The fix is application-level. Publish a timestamp inside the payload, and have consumers reject anything older than a defined threshold. Some brokers and MQTT 5.0 features offer message expiry, but you should not assume it exists across every broker.

Retained Messages on High-Frequency Topics

Retaining a topic that publishes ten times per second is wasteful. The broker rewrites storage constantly, and the retained value adds nothing because live data is always flowing. Reserve retention for low-frequency state topics.

Unintended Wildcard Floods

As noted, a wildcard subscription can pull in every retained message under a tree. On a shared broker with thousands of topics, that burst can overwhelm a client or blow past memory limits. Scope subscriptions tightly and audit retained topics regularly.

Security and Data Leakage

Retained messages persist on the broker and are delivered to any future subscriber authorized for the topic. If access control is loose, a new client can subscribe to a wildcard and harvest every stored value in the namespace. Treat retained topics as persistent storage and apply the same access rules you would to a database. The same principle of careful data handling applies across other connected systems, whether you are weighing household insurance coverage options or designing a medical data pipeline: persistence without governance becomes a liability.

Assuming Every Broker Stores Them

The MQTT specification does not mandate that a broker store retained messages, and limits vary by implementation. Broker documentation should be checked for maximum retained message counts, payload size caps, and whether retained messages survive a broker restart. Some lightweight brokers keep them in memory only.

What MQTT 5.0 Changed

MQTT 5.0, published as an OASIS standard in March 2019, added subscription options that give clients more control over retained message delivery.

Retain Handling lets a subscriber specify whether retained messages should be sent at subscribe time. Value 0 sends them always, value 1 sends them only if the subscription did not already exist, and value 2 suppresses them entirely. This is useful when a client reconnects and does not want to reprocess old snapshots.

Retain As Published controls whether the RETAIN flag is preserved when a message is forwarded, which matters for bridge and other forwarding setups where flags can otherwise get rewritten.

Retain Available appears in the CONNACK packet, telling clients whether the broker supports retained messages at all. A client can check this before relying on the feature.

If you are running MQTT 3.1.1, none of these options exist. That is a strong argument for planning an upgrade path if retention is central to your design.

Tips That Save Real Debugging Time

Working with retained messages long enough teaches a few lessons the hard way.

Audit retained topics regularly. Subscribe to `#` on a test client and look at what comes back. You will often find topics from decommissioned devices, test scripts, and forgotten experiments. Clean them with zero-byte publishes.

Never retain command topics. A retained “turn on” command will fire again for every new subscriber. That is a classic way to switch on a device in the middle of the night. Retain state, not actions.

Set a convention and document it. Decide which topic branches carry retained state and stick to it. A namespace like `state/` versus `events/` makes the distinction visible in the topic tree itself.

Test the cold-start path. Restart your consumer and confirm it receives exactly the retained messages you expect, no more. This catches wildcard floods and stray retained topics before production does.

Watch memory on constrained brokers. Retained messages consume broker memory. On a Raspberry Pi running a small broker, a few hundred retained payloads of a few kilobytes each add up.

The same discipline of testing the edge cases applies to consumer-facing products generally, whether that is a creative tool’s pricing plans or a connected device fleet: the assumptions that break are usually the ones nobody checked. Even planning something as low-tech as a family board game night rewards reading the rules carefully before play, and MQTT retention is no different.

Conclusion

Retained messages are one of MQTT’s most useful features precisely because they are so narrow. They store one current value per topic and hand it to whoever subscribes next. That simple behavior makes dashboards instant, device discovery automatic, and status monitoring reliable across restarts and reconnects.

The trouble starts when teams treat retention as a message history, forget to clean up dead topics, or retain high-frequency streams that never needed it. Used with clear conventions, timestamped payloads, tight access control, and regular audits, retained messages do exactly what they promise: they make sure the last known state is never a mystery. If you take one thing away, make it this: retain state, not events, and clean up after yourself.

FAQ

What is the difference between a retained message and a normal MQTT message?

A normal message is delivered only to clients connected at the moment of publishing and is then gone. A retained message is stored by the broker and delivered to any client that subscribes later, with the RETAIN flag set to indicate it is stored data rather than a live event.

How do I delete a retained message?

Publish a message with a zero-byte payload and the RETAIN flag set to 1 on that topic. The broker removes the stored message. Be careful to send a truly empty payload, not an empty string or a null value, or the broker will store that instead.

Does every MQTT broker support retained messages?

Most mainstream brokers do, but the specification does not require it, and limits vary. Some brokers keep retained messages in memory only and lose them on restart. MQTT 5.0 lets a client check the Retain Available flag in the CONNACK packet before relying on the feature.

Can a retained message expire automatically?

In MQTT 3.1.1 there is no expiry mechanism, so a retained message stays until it is replaced or deleted. MQTT 5.0 adds message expiry interval support, but broker implementation varies. In practice, most teams embed a timestamp in the payload and let consumers discard old values. (MQTT)

Why did my client receive dozens of messages right after subscribing?

A wildcard subscription can match many topics, and the broker sends one retained message per matching topic at subscribe time. Subscribing to a broad filter like `#` on a busy broker can produce a large burst. Scope subscriptions narrowly and audit which topics carry retained values.

Should I retain command messages like “turn on” or “open valve”?

No. Retaining a command means every future subscriber triggers it again, which can switch on equipment unexpectedly. Retain state topics such as current mode or status, and publish commands as normal, non-retained messages that only reach clients listening at that moment.

on this page