Last Updated: November 21, 2025
MQTT
Message Queuing Telemetry Transport protocol
IoT
Protocol
MQTT Basics
Protocol Type
Lightweight publish/subscribe messaging protocol
Port 1883
Default MQTT port (unencrypted)
Port 8883
MQTT over TLS/SSL (encrypted)
Port 8083/8084
MQTT over WebSockets (8083 plain, 8084 SSL)
Client-Broker Model
Clients connect to broker; broker routes messages
Publish/Subscribe
Decoupled communication via topics
TCP/IP Based
Runs over TCP/IP for reliable delivery
Low Bandwidth
Minimal overhead; ideal for constrained networks
Popular MQTT Brokers
Mosquitto
Open-source, lightweight broker from Eclipse
HiveMQ
Enterprise MQTT broker with cloud offering
EMQX
Scalable, distributed MQTT broker
AWS IoT Core
Managed MQTT broker in AWS
Azure IoT Hub
Microsoft's cloud MQTT service
CloudMQTT
Hosted Mosquitto broker service
broker.hivemq.com
Free public HiveMQ test broker
test.mosquitto.org
Free public Mosquitto test broker
Mosquitto Installation
Ubuntu/Debian
sudo apt install mosquitto mosquitto-clients
macOS
brew install mosquitto
Windows
Download from mosquitto.org/download
Start Broker
mosquitto -c /etc/mosquitto/mosquitto.conf
Start as Service (Linux)
sudo systemctl start mosquitto
Enable on Boot
sudo systemctl enable mosquitto
Topic Structure
Topic Hierarchy
Use forward slashes: home/livingroom/temperature
Case Sensitive
home/temp and Home/temp are different topics
No Leading Slash
Use sensor/temp not /sensor/temp
UTF-8 Encoding
Topics are UTF-8 encoded strings
Max Length
65535 characters maximum (practical limit much lower)
Avoid Spaces
Use underscores or camelCase: living_room or livingRoom
Best Practice
3-7 levels deep: company/location/building/floor/room/device/sensor
Wildcards
+ (Single Level)
Matches one topic level: home/+/temperature matches home/kitchen/temperature
# (Multi Level)
Matches multiple levels: home/# matches home/kitchen/temperature/sensor1
# Must Be Last
# wildcard must be last character: home/# not home/#/temp
Subscribe Only
Wildcards only work in subscriptions, not publishes
Example: +/+/temperature
Matches any 2-level hierarchy before /temperature
Example: sensors/#
Matches all topics starting with sensors/
QoS (Quality of Service) Levels
QoS 0 - At Most Once
Fire and forget; no acknowledgment; fastest
QoS 1 - At Least Once
Guaranteed delivery; may receive duplicates; requires ACK
QoS 2 - Exactly Once
Guaranteed delivery exactly once; slowest; 4-way handshake
QoS 0 Use Case
Temperature readings (data frequently updated)
QoS 1 Use Case
Door open/close events (important but duplicates OK)
QoS 2 Use Case
Billing transactions (must not duplicate)
Subscription QoS
Broker delivers messages at min(publish QoS, subscribe QoS)
Publish Commands (mosquitto_pub)
mosquitto_pub -t topic -m "msg"
Publish message to topic on localhost
-h host
Specify broker hostname/IP
-p port
Specify broker port (default 1883)
-q qos
Set QoS level (0, 1, or 2)
-r
Set retained flag
-u username -P password
Authenticate with username and password
-i client_id
Set client ID (auto-generated if not specified)
-d
Enable debug messages
Example
mosquitto_pub -h broker.hivemq.com -t home/temp -m "22.5" -q 1
Subscribe Commands (mosquitto_sub)
mosquitto_sub -t topic
Subscribe to topic on localhost
-h host -p port
Specify broker hostname and port
-t topic1 -t topic2
Subscribe to multiple topics
-q qos
Set QoS level for subscription
-v
Verbose; show topic name with message
-u username -P password
Authenticate with credentials
-C count
Disconnect after receiving count messages
Example Wildcard
mosquitto_sub -h broker.hivemq.com -t "home/#" -v
Retained Messages
Purpose
Broker stores last message; new subscribers get it immediately
Set Retained
Publish with retain flag: mosquitto_pub -r -t topic -m "msg"
One Per Topic
Only one retained message per topic
Clear Retained
Publish empty message with retain: mosquitto_pub -r -t topic -n
Use Case
Device status, configuration, last known values
QoS Independent
Retained flag works with any QoS level
Last Will and Testament (LWT)
Purpose
Broker publishes message if client disconnects unexpectedly
Set at Connection
LWT configured during CONNECT packet
LWT Topic
Topic where LWT message is published
LWT Message
Message content (e.g., "offline", "disconnected")
LWT QoS & Retain
Can set QoS level and retain flag for LWT
Use Case
Device status monitoring (online/offline)
mosquitto_pub LWT
mosquitto_pub --will-topic status --will-payload "offline" -t topic -m "msg"
Clean Session
Clean Session = True
Broker discards previous session; no stored messages/subscriptions
Clean Session = False
Broker stores session; queues messages for offline client
Persistent Session
Requires unique client ID and clean_session=false
Stored Data
Subscriptions, QoS 1/2 messages not yet acknowledged
Use Case
Mobile apps with intermittent connectivity
Keep Alive
Purpose
Detect broken connections; client pings broker periodically
Default Value
60 seconds (configurable)
PINGREQ/PINGRESP
Client sends PINGREQ; broker responds with PINGRESP
Timeout
Broker waits 1.5x keep-alive interval before disconnect
mosquitto_pub -k 30
Set keep-alive to 30 seconds
Security
Username/Password
Basic authentication with credentials
TLS/SSL Encryption
Encrypt traffic using port 8883
Client Certificates
Mutual TLS authentication
ACL (Access Control)
Topic-level permissions per user/client
mosquitto_passwd
Create password file: mosquitto_passwd -c passfile username
Configure Auth
In mosquitto.conf: password_file /etc/mosquitto/passwd
TLS Connection
mosquitto_pub --cafile ca.crt --cert client.crt --key client.key
Python Example (paho-mqtt)
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print(f"Connected with code {rc}")
client.subscribe("home/temperature")
def on_message(client, userdata, msg):
print(f"{msg.topic}: {msg.payload.decode()}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.hivemq.com", 1883, 60)
client.publish("home/temperature", "22.5", qos=1)
client.loop_forever()
Pro Tips:
- Use QoS 0 for Telemetry: Frequent sensor data doesn't need guaranteed delivery
- Retain for Status: Use retained messages for device status (online/offline)
- LWT for Monitoring: Always configure Last Will for critical devices
- Topic Naming: Use consistent hierarchy; avoid spaces and special characters
- Client IDs: Use unique, meaningful client IDs for persistent sessions
- Wildcard Performance: # wildcard at root (e.g., #) subscribes to everything; use sparingly
- Security First: Always use TLS/SSL in production; public brokers are for testing only
- Test with Mosquitto: mosquitto_pub and mosquitto_sub are essential debugging tools