MQTT is the application protocol that most IoT devices use to send data to a back end and receive commands from it. It was designed in 1999 for monitoring oil pipelines over satellite links, so it had to be small, tolerate links that drop without warning, and use as few bytes as possible. Those constraints describe most IoT deployments, and after it became an open standard it became the common language between devices and IoT platforms.
The protocol is simple to learn, but using it well involves decisions about topic structure, delivery guarantees and session handling that are easy to get wrong. This guide covers the mechanics and then the practical choices.
The publish-subscribe model
MQTT is a publish-subscribe protocol. Clients do not talk to each other; they all connect to a broker. A client publishes a message to a named topic, and the broker delivers it to every client that has subscribed to that topic. The publisher does not know or care who is listening.
This decoupling is the point. A sensor publishes temperature readings to one topic; a dashboard, an alarm service and a database writer can all subscribe without the sensor’s firmware changing.
+ and # wildcards let one subscription cover many topics.A connection is a long-lived TCP session, normally wrapped in TLS, on port 1883 for plain MQTT and 8883 for TLS by convention. MQTT can also run over WebSocket so that browser applications can subscribe directly. For devices that cannot afford TCP at all, MQTT-SN is a variant for UDP and non-IP networks that a gateway bridges to a normal broker.
Topics
A topic is a UTF-8 string organized in levels separated by slashes, such as:
factory/line-3/press-7/temperature
Subscribers can use wildcards. The single-level wildcard + matches one level (factory/line-3/+/temperature matches every machine on line 3), and the multi-level wildcard # matches everything below (factory/line-3/#). Topics are not declared in advance; they exist when someone publishes or subscribes.
Topic design is the most consequential decision in an MQTT system. A hierarchy that runs from general to specific makes wildcard subscriptions useful and access control manageable. Common conventions separate telemetry from commands, and include the device identity in the topic so that the broker can enforce that each device only publishes to its own branch. Sparkplug is a specification that standardizes topic layout and payload format for industrial use.
Quality of Service
Every publish carries a Quality of Service level that defines the delivery guarantee between the client and the broker.
QoS 0, at most once. The message is sent once with no acknowledgment. If the connection drops at the wrong moment it is lost. Cheapest, and fine for frequent readings where the next one will arrive soon anyway.
QoS 1, at least once. The sender keeps the message until the broker acknowledges it, and resends if no acknowledgment arrives. The message can therefore arrive more than once, so consumers must tolerate duplicates. This is the common default for telemetry and commands.
QoS 2, exactly once. A four-step handshake ensures single delivery. It costs more round trips and state, and is reserved for things like billing events where a duplicate is as bad as a loss.
The level applies per hop; the broker delivers to each subscriber at the lower of the publisher’s and the subscriber’s level.
Sessions, keep-alive and last will
When a client connects it tells the broker whether to keep session state. A persistent session stores the client’s subscriptions and any QoS 1 or 2 messages that arrive while it is offline, delivering them on reconnect. This is how a device that sleeps for an hour receives the commands sent while it was away. The cost is broker memory, so platforms limit how much they queue and for how long.
Clients send a periodic keep-alive so that the broker can detect a dead connection. If a client disappears without a proper disconnect, the broker publishes its Last Will and Testament, a message registered at connect time, typically to a status topic.
A retained message is the last message on a topic that the broker stores and delivers immediately to any new subscriber. Publishing device status as retained means a dashboard that starts up sees the current state of every device at once.
What MQTT 5 added
MQTT 3.1.1, standardized by OASIS in 2014, is still the most widely deployed version. MQTT 5, published in 2019, addressed gaps found in large deployments:
- Reason codes on acknowledgments, so a client learns why a publish or subscribe was refused instead of being silently disconnected.
- User properties, arbitrary key-value metadata on messages, useful for content type, tracing identifiers or routing hints.
- Message expiry, so that a stale command is discarded rather than delivered to a device that reconnects a day later.
- Shared subscriptions, where a group of consumers split the messages on a topic between them for load balancing.
- Topic aliases and an explicit session expiry interval, replacing the clean-session flag.
Most brokers and platforms support both versions. New designs should use 5 unless a device library does not.
Security
MQTT has no encryption or authentication of its own; it relies on the transport. In practice that means TLS with the device presenting an X.509 certificate for mutual authentication, or a token over TLS where certificates are impractical. Authorization is enforced by the broker through access control lists that bind each client identity to the topics it may use. A broker that lets any device subscribe to # has made every device a listener on every other. The device identity guide covers the certificate side.
When to use MQTT and when not to
MQTT suits devices that have an IP connection, can keep a TCP session open at least intermittently, and send many small messages to a back end that fans them out to several consumers. That describes most Wi-Fi, Ethernet and cellular IoT devices, and most gateways.
It is a poor fit when the device cannot sustain TCP and TLS, which points to CoAP over DTLS or MQTT-SN. It is also the wrong tool for request-response interactions where a client wants an immediate answer from a specific server; MQTT 5 adds response topics and correlation data for the purpose, but a REST or CoAP call is more natural. For very high throughput between back-end services, a dedicated message queue or streaming platform is a better choice than the device-facing broker. And for industrial real-time control, fieldbus protocols and OPC UA remain the standards, with MQTT used to carry data upward from them.
A minimal example
A device reports a reading with QoS 1 and marks its presence with a retained status message and a will:
CONNECT clientId=sensor-0042, will: devices/sensor-0042/status = "offline"
PUBLISH devices/sensor-0042/status "online" (retained)
PUBLISH devices/sensor-0042/telemetry {"t":21.4,"h":48} QoS 1
SUBSCRIBE devices/sensor-0042/cmd/# QoS 1
The back end subscribes to devices/+/telemetry and devices/+/status, and publishes commands to devices/sensor-0042/cmd/set-interval.
Where to go next
- CoAP explained covers the main alternative for constrained devices.
- IoT platforms explained describes the managed brokers most deployments use.
- IoT connectivity overview explains the radio layer underneath.
- How IoT works: from sensor to cloud and back places MQTT in the full data path.
Topics: MQTT, protocols, messaging, publish-subscribe