Using the retained message flag in MQTT with Python
This script subscribes to an MQTT topic and prints the retained flag for each received message, demonstrating how to distinguish retained messages from normal ones.
pip install paho-mqtt
Python code
32 linesimport paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# Subscribe to a topic and check retained flag
client.subscribe("test/retained")
print("Subscribed to test/retained")
def on_message(client, userdata, msg):
# msg.retain is the MQTT retained flag (True if retained, False if normal)
print(f"Topic: {msg.topic}")
print(f"Payload: {msg.payload.decode()}")
print(f"Retained flag: {msg.retain}")
print("-" * 30)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("test.mosquitto.org", 1883, 60)
client.loop_start()
# Publish a normal message (retained=False)
client.publish("test/retained", "normal message", retain=False)
# Publish a retained message (retained=True)
client.publish("test/retained", "retained message", retain=True)
import time
time.sleep(2)
client.loop_stop()
client.disconnect()
Output
Connected with result code 0
Subscribed to test/retained
Topic: test/retained
Payload: normal message
Retained flag: False
------------------------------
Topic: test/retained
Payload: retained message
Retained flag: True
------------------------------
How it works
The on_connect callback is triggered when a connection is established; here we subscribe to the topic. The on_message callback receives each message, and msg.retain indicates whether it is a retained message (True) or a normal one (False). Retained messages are stored by the broker and sent to new subscribers, so the flag is crucial for handling stateful data. The script briefly sleeps to allow time for messages to be delivered before disconnecting.
Common mistakes
- Forgetting to call `loop_start()` or `loop_forever()` to process incoming messages
- Checking `msg.retain` on the publish side instead of the receive side
- Assuming retained messages are resent to existing subscribers when updated — they are not
Variations
- Use `client.loop_forever()` in a blocking script instead of `loop_start()` with a sleep
- Publish with `retain=True` to set a last known good value for a sensor topic
Real-world use cases
- An IoT device publishes its latest status with a retained flag so new subscribers instantly get the current state.
- A home automation hub sends retained configuration topics that devices read upon connecting.
- A monitoring service checks the retained flag to differentiate between stale cached data and live updates.
Sponsored
More from Streaming & messaging
- At Most Once Fire-and-Forget Mock in Python easy
- Batch Consume Process Commit Pattern in Python medium
- Build a Streaming Messaging Helper in Python easy
- Dead Letter Queue Failed Messages List Mock in Python easy
- Dedupe processed message IDs in Python easy
- Event Envelope with Schema Version Field in Python easy
Keep learning
Related tutorials and quizzes for this topic.