The most surprising thing about MQTT is that despite its popularity in IoT, it’s fundamentally a publish/subscribe system that doesn’t actually store messages itself; it just ferries them between clients.
Let’s see this in action. We’ll use two simple Python clients. First, the subscriber.
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected successfully")
client.subscribe("home/livingroom/temperature")
else:
print(f"Connection failed with code {rc}")
def on_message(client, userdata, msg):
print(f"Received message: {msg.payload.decode()} on topic {msg.topic}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("mqtt.eclipseprojects.io", 1883, 60)
client.loop_forever()
Now, the publisher.
import paho.mqtt.client as mqtt
import time
client = mqtt.Client()
client.connect("mqtt.eclipseprojects.io", 1883, 60)
topic = "home/livingroom/temperature"
message = "22.5"
client.publish(topic, message)
print(f"Published '{message}' to topic '{topic}'")
client.loop_stop() # Stop the loop if you don't need to process replies
When you run the subscriber first and then the publisher, you’ll see the "Published…" message in the publisher’s console, and immediately after, "Received message: 22.5 on topic home/livingroom/temperature" in the subscriber’s console. The MQTT broker, in this case, mqtt.eclipseprojects.io, simply routed the message from the publisher to any client subscribed to that specific topic.
This publish/subscribe model is MQTT’s core strength. Instead of clients directly addressing each other (which would require knowing each other’s addresses and managing connections), they communicate through a central broker using topics. Topics are hierarchical strings, like file paths, e.g., company/department/device/status. A client publishes a message to a topic, and any client that has subscribed to that topic receives the message. This decouples publishers and subscribers: they don’t need to know about each other’s existence or be online at the same time.
The broker’s role is crucial. It handles client connections, authenticates them (if configured), receives messages from publishers, and delivers them to subscribers based on their subscriptions. Key configuration parameters for the broker include the port (commonly 1883 for unencrypted, 8883 for TLS), and potentially username/password authentication. For clients, important settings are the broker address, port, and the client ID (which must be unique per connected client on a given broker). QoS levels (0, 1, 2) dictate the reliability of message delivery, with higher QoS levels offering stronger guarantees at the cost of increased overhead.
A common point of confusion is the concept of "retained messages." If a publisher sends a message with the retain flag set, the broker will store the last message published to that topic. When a new client subscribes to that topic, the broker will immediately send them this last retained message. This is useful for providing the "last known state" of a device without requiring it to be online to send an initial message upon subscription. For example, if a smart light’s status is published with the retain flag, a new client connecting to the system will immediately know if the light is currently on or off.
The next step is to explore Quality of Service (QoS) levels and their impact on message delivery guarantees.