Networking
MQTT — Message Queuing Telemetry Transport
A lightweight publish/subscribe messaging protocol built on top of TCP. Instead of one device talking directly to another, every device talks to a central broker — publishers send messages tagged with a topic, and the broker fans each one out to whoever subscribed to that topic, with no publisher ever needing to know who (or how many) is listening.
- What it is
- A publish/subscribe messaging protocol over TCP, routed through a central broker.
- Mental model
- A radio station: publishers broadcast on a channel (topic), subscribers tune in — neither side needs to know who else is listening.
- Key numbers
- 3 QoS levels (0/1/2), topic wildcards
+and#, persistent TCP connection per client. - Reach for it when
- You have many-to-many fan-out (fleet telemetry, dashboards) and a broker is acceptable infrastructure.
The pub/sub model
This decoupling is the whole point: a publisher doesn't need to know how many subscribers exist, whether they're online right now, or where they are — it just publishes. New subscribers can appear later and start receiving without the publisher changing anything.
Topics and wildcards
A topic is a slash-separated hierarchy the application defines itself
— there's no fixed schema, e.g. factory/line1/press3/temperature.
Subscribers can match a specific topic exactly, or use wildcards:
+- Matches exactly one topic level.
factory/+/press3/temperaturematches any line. #- Matches any number of remaining levels — must be the last character.
factory/line1/#matches everything underline1.
Quality of Service: 0, 1, 2
Unlike CoAP's binary confirmable/non-confirmable choice, MQTT has three delivery guarantees, chosen per-message by the publisher:
| QoS | Guarantee | Mechanism |
|---|---|---|
| 0 | At most once | Fire-and-forget — no acknowledgement, message may be lost, never duplicated. |
| 1 | At least once | Sender keeps retrying until it gets a PUBACK — message will arrive, but a lost ACK can cause a duplicate delivery. |
| 2 | Exactly once | A four-packet handshake (PUBLISH → PUBREC → PUBREL → PUBCOMP) that both guarantees delivery and de-duplicates — the most expensive, reserved for messages where duplicates would actually cause harm (e.g. "charge this transaction"). |
Note QoS is between each client and the broker independently — a publisher can send at QoS 2 while a given subscriber receives at whatever QoS it subscribed with, whichever is lower wins for that hop.
Retained messages
A publisher can mark a message retained; the broker keeps the latest retained message on that topic and immediately sends it to any client that subscribes later — without waiting for the next publish. This is how a newly-connected dashboard immediately shows "last known temperature" instead of a blank value until the next reading arrives.
Last Will and Testament
When connecting, a client can register a will message
with the broker — a topic and payload the broker will publish
on the client's behalf if that client disconnects
ungracefully (network drop, crash, power loss) rather than sending a
clean DISCONNECT. This is the standard way to get
reliable "device went offline" notifications without polling — a
dashboard subscribes to devices/+/status and finds out
immediately, from the broker, when a device vanishes.
The packet types, briefly
| Packet | Purpose |
|---|---|
| CONNECT / CONNACK | Client authenticates and opens a session with the broker. |
| PUBLISH | Send a message on a topic, at a chosen QoS. |
| SUBSCRIBE / SUBACK | Register interest in a topic (filter), broker confirms the granted QoS. |
| PINGREQ / PINGRESP | Keepalive — lets the broker detect a dead connection before the TCP stack would. |
| DISCONNECT | Clean shutdown — explicitly tells the broker not to fire the will message. |
MQTT vs. CoAP vs. AMQP
| MQTT | CoAP | AMQP | |
|---|---|---|---|
| Model | Publish/subscribe via broker | REST request/response | Message queues via broker (routing, not just topics) |
| Transport | TCP | UDP (usually) | TCP |
| Connection state | Persistent connection per client | None required | Persistent connection per client |
| Typical fit | Fleet telemetry, many-to-many fan-out, constrained-but-not-tiny devices | Individually constrained devices, request/response device control | Enterprise messaging with complex routing and delivery guarantees |
Real-world applications
- IoT device fleets — AWS IoT Core and Azure IoT Hub both use MQTT as their primary device-to-cloud protocol.
- Home automation — Home Assistant and countless smart-home setups use an MQTT broker (often Mosquitto) as the message bus between devices and automations.
- Industrial telemetry (Sparkplug B) — a standardized MQTT payload format used across factory-floor sensor and PLC data collection.
- Facebook Messenger (historically) — MQTT was famously chosen for its chat delivery precisely because of its low overhead over unreliable mobile networks.
- Vehicle telematics — connected-car platforms use MQTT to stream diagnostics and location data from vehicles to a backend.
Gotchas
- QoS 1 will occasionally deliver duplicates — if the application isn't idempotent to duplicate messages, QoS 1 alone doesn't save it.
- A broker is a single point of failure and a piece of infrastructure a raw-socket or CoAP design doesn't need — factor that operational cost in, not just the wire protocol's elegance.
- Retained messages and the will message are easy to forget about when debugging "why did a stale value show up" — check for a retained flag before assuming a device is actually publishing that value right now.
- MQTT's persistent TCP connection is exactly the cost CoAP was designed to avoid on genuinely tiny, battery-constrained nodes — MQTT tends to fit better once a device already has a stable network connection to spare.