Normally an MQTT broker forwards a message to the clients that are subscribed right now and then forgets it. A client that subscribes a minute later sees nothing until the next publish. Retained messages solve this: the broker stores the last retained message for a topic and hands it to every new subscriber immediately, so they always start with the current state.
How retained messages work
Retention is controlled by a single bit, the RETAIN flag in the PUBLISH packet. When the broker receives a publish with RETAIN=1:
- It delivers the message to current subscribers, as usual.
- It stores the message (topic, payload, QoS) as the retained message for that topic, replacing any previous one. There is at most one retained message per topic.
- Whenever a client later subscribes with a filter that matches the topic, the broker sends the retained message right after the
SUBACK, with the retain flag set so the client knows it is a stored value.
10:00 device PUBLISH acme/th-01/setpoint "21.0" retain=1 -> broker stores it
10:05 device PUBLISH acme/th-01/setpoint "22.5" retain=1 -> replaces "21.0"
10:30 app SUBSCRIBE acme/+/setpoint
10:30 broker PUBLISH acme/th-01/setpoint "22.5" retain=1 -> delivered instantlyWildcard subscriptions receive the retained messages of every matching topic, which is how a dashboard that subscribes to acme/+/status can paint the state of all devices on startup.
The retain flag on delivery
In MQTT 3.1.1, a message forwarded to an existing subscriber always has the retain flag cleared; the flag is only set when the message is sent because of a new subscription. MQTT 5 keeps that default but adds the Retain As Published subscription option, which preserves the original flag — useful for bridges.
Without retention, a newly started dashboard would show empty tiles until every device happened to publish again — which for a door sensor or a configuration value could take hours. With retention, the first screen is already correct.
When to use retained messages
- Device state —
online/offline, on/off, current mode. - Configuration and setpoints — a device that reboots subscribes and immediately gets its config.
- Slow-changing values — firmware version, location, last known reading.
- Presence together with a retained Last Will message, so the offline status sticks.
Avoid retaining:
- Events and commands — a retained
unlock-doorcommand would be replayed to every new subscriber, possibly days later. - High-frequency streams — retaining is harmless but pointless when the next value arrives in a second.
- Per-message topics — topics containing IDs or timestamps leave thousands of stale retained messages behind.
How to clear a retained message
To delete a retained message, publish to the same topic with the retain flag set and a zero-length payload. The broker removes the stored message and does not store the empty one. Current subscribers do receive the empty message, so make your code ignore empty payloads.
# -r = retain, -n = send a null (zero-length) payload
mosquitto_pub -h broker.hivemq.com -t 'testmqtt/demo/status' -r -nclient.publish('testmqtt/demo/status', '', { retain: true, qos: 1 });To clear many topics at once, subscribe with a wildcard, collect every topic that delivers a message with the retain flag, and publish an empty retained payload to each. There is no standard "delete all retained" command — some brokers offer admin tools, but they are broker-specific.
Retained messages vs persistent sessions
Retained messages are often confused with persistent sessions, but they answer different questions:
| Retained message | Persistent session | |
|---|---|---|
| Scope | Per topic, shared by all subscribers | Per client ID |
| What is kept | Only the latest message | Subscriptions plus every missed QoS 1/2 message |
| Who receives it | Any client that subscribes later | Only that client when it reconnects |
| Typical use | Current state | Not missing events |
A device that needs both its current configuration and every command sent while it was offline uses both: a retained config topic and a persistent session for the command topic. The QoS guide explains how sessions and QoS interact.
Retained messages also keep their QoS. When the broker delivers a stored message to a new subscriber, the usual downgrade rule applies: the subscriber receives it at the lower of the original QoS and its subscription QoS.
Retained messages in MQTT 5
MQTT 5 adds finer control over retained messages:
| Feature | What it does |
|---|---|
| Retain Handling (subscription option) | 0 = send retained messages on subscribe (default), 1 = only if the subscription is new, 2 = never send them |
| Retain As Published (subscription option) | Keeps the original retain flag on forwarded messages |
| Message Expiry Interval (publish property) | The broker discards the retained message after the given number of seconds |
| Retain Available (CONNACK property) | Tells the client whether the broker supports retained messages at all |
Message expiry is especially handy: a retained sensor reading that expires after an hour can never be mistaken for a fresh one. See MQTT 5 vs 3.1.1 for the full list of changes.
Test retained messages
- Publish
onlinewith Retain checked totestmqtt/your-id/status. - Disconnect, reconnect and subscribe to
testmqtt/your-id/#. The message arrives instantly, marked as retained. - Publish an empty payload with Retain checked, resubscribe — nothing arrives. The retained message is gone.
Try it in the online MQTT client
The online MQTT client shows a retained badge on stored messages, which makes stale state easy to spot. For a broader checklist, see how to test an MQTT broker.
Frequently asked questions
How do I delete a retained message in MQTT?
Publish a message with the retain flag set and a zero-length (empty) payload to the same topic. The broker removes the stored retained message, and the empty message is not kept. With mosquitto_pub use -r -n.
How many retained messages can a topic have?
One. The broker keeps only the most recent retained message per topic; each new retained publish replaces the previous one.
Is a retained message the same as a persistent session?
No. A retained message is the last value of a topic, delivered to any new subscriber. A persistent session queues messages for one specific client while it is offline. They solve different problems and are often used together.