MQTT Retained Messages
MQTT is a pub-sub protocol — subscribers receive only messages published while they're subscribed. The retain flag is the escape hatch: tell the broker "remember this message and replay it to anyone who subscribes later." Used right, retained messages give late-joining clients instant access to the current state of every device. Used wrong, they replay stale events that confuse newly-connected systems.
How retain works
- Publisher sends a message with RETAIN=true.
- Broker delivers the message to all current subscribers (normal pub-sub flow).
- Broker also stores the message as the topic's "retained value," replacing any previous retained value.
- When a new subscriber subscribes, the broker immediately delivers the retained message for any matching topic.
One retained message per topic. Publishing a new retained message overwrites the previous one. Publishing a normal (non-retained) message does NOT affect the retained value.
When to retain
- Current device state. "Device X is online" — anyone subscribing should see the current status.
- Latest sensor reading. "Current temperature in room 204" — useful for dashboards opening fresh.
- Configuration values. "Threshold for alert is 80°C" — devices joining need to know the current setting.
- Static metadata. "Device firmware version is 2.3.1" — survives client reconnects.
When NOT to retain
- Discrete events. "Door opened" — re-delivering an old event to a fresh subscriber implies it just happened, which is wrong.
- Stream of readings. "Temperature was 22.4 at 14:32" — only the most recent value is retained; intermediate readings are lost.
- Command messages. "Turn on the light" — replaying old commands when new subscribers connect causes unintended actions.
- Logs. Each log entry is a separate event; retain doesn't help.
The Last Will and Testament pattern
Retain combined with LWT (Last Will and Testament) gives reliable device-status tracking:
- When a device connects, it registers an LWT: "If I disconnect ungracefully, publish 'offline' to topic
device/abc/statuswith retain=true." - Immediately after connecting, the device itself publishes 'online' to
device/abc/statuswith retain=true. This replaces the LWT-stale-'offline' from a previous session. - If the device crashes, the broker notices the broken connection and publishes the LWT — 'offline' on the status topic with retain.
- Any subscriber, current or future, sees the correct status.
This is the canonical "is this device alive" pattern for MQTT systems.
Clearing a retained message
To delete a retained value, publish an empty payload (zero bytes) to the topic with retain=true:
publish topic="device/abc/status" payload="" retain=true
The broker deletes the retained message. The empty publish is still delivered to current subscribers (some clients filter empty payloads, some don't).
Retained messages and QoS
The retained message is stored with the QoS level it was published at. When delivered to a new subscriber, the QoS is the minimum of the subscriber's requested QoS and the retained value's QoS. So:
- Published QoS 0, subscribed QoS 2 → delivered at QoS 0 (no acknowledgement).
- Published QoS 2, subscribed QoS 0 → delivered at QoS 0.
If you care about delivery guarantees for retained values, publish them at QoS 1 or 2.
Storage and lifecycle
Each topic with a retained message consumes storage on the broker. Per topic the storage is small, but with millions of topics retained values can occupy gigabytes. Brokers vary in:
- Persistence — do retained messages survive broker restart? (Most yes; some lightweight in-memory brokers no.)
- Replication — in HA broker clusters, are retained messages replicated? (Usually yes.)
- Garbage collection — retained messages persist forever unless explicitly cleared. Audit periodically for stale topics.
Retain and wildcard subscriptions
When a client subscribes to a wildcard topic, the broker delivers retained messages for every matching topic immediately. Subscribing to # on a busy broker can deliver thousands of retained messages instantly. Plan client buffer sizes accordingly.
Retain in MQTT 5
MQTT 5 added options that change retain behavior:
- Retain Available — broker advertises whether it supports retain at all.
- Subscription option "Retain Handling" — subscriber can choose to receive retained messages always, only on new subscription (not on re-subscription), or never. Useful for clients that don't want stale state on reconnect.
- Message Expiry Interval — retained messages can have a TTL; the broker deletes them after expiry.
The expiry option is particularly useful for retained sensor readings that age into irrelevance.
Common retained-message patterns
- Status topic per device.
device/X/statusretained with online/offline. - Last reading per measurement.
sensor/X/temperatureretained with the latest value plus timestamp. - Configuration registry.
config/X/setpointretained with the current setpoint. - Discovery topics. Home Assistant uses retained MQTT discovery messages so HA learns about devices automatically.
Frequently Asked Questions
What is a retained message?
A regular MQTT message with the RETAIN flag set. The broker stores the most recent retained message per topic. When a new subscriber subscribes to a topic with a retained message, they immediately receive that last retained value — even though the publisher may have sent it minutes or days ago. Each topic holds at most one retained message; a new retained publish replaces the previous one.
When should I use retained messages?
For "current state" topics where late-joining subscribers need to know the last value: device online/offline status, current temperature reading, configured threshold, last command received. Don't use it for events ("door opened at 14:32") because subscribing later and receiving a stale opening event is misleading.
How do I clear a retained message?
Publish an empty payload to the same topic with the retain flag set. The broker deletes the retained message for that topic. New subscribers no longer receive the previous value on subscribe. This is the only way to remove a retained message without changing topic name.
What is the LWT (Last Will and Testament) pattern?
A message a client registers with the broker when connecting. If the client disconnects ungracefully, the broker publishes the LWT message to its specified topic. Combined with a retained LWT on a status topic (e.g., "device/dev_abc/status"), the system has a reliable way to detect when devices crash or lose connectivity, even when they can't announce their own departure.
Do retained messages survive broker restarts?
Depends on broker configuration. Most brokers persist retained messages to disk by default; restarts don't lose them. Some lightweight or in-memory brokers lose retained messages on restart. Check the broker docs and configure persistence for any retained data you care about.
Related Guides
More From This Section
All IoT Protocols Guides
MQTT, CoAP, Zigbee, Thread, Z-Wave, Matter, Modbus, and OPC UA.
Bluetooth Low Energy for IoT
How BLE works for IoT — advertising vs connections, GATT profile, pairing, BLE 5 features, BLE mesh for multi-device…
CoAP Protocol Deep Dive
How CoAP works — request/response over UDP, confirmable vs non-confirmable messages, observe, block-wise transfer, DTLS…
Run a Speed Test
Measure download, upload, ping, and jitter in your browser.