All writing
4 min read

MQTT: designed for the network that isn't there

MQTT solves a different problem than the real-time protocols I work in day to day — not lower latency, but survival on links that drop, sleep and reconnect. What the broker actually buys you, why publish/subscribe decouples devices that were never meant to know about each other, and what building one taught me before I understood why it mattered.

Asghar Ali · Chief Technology Officer, Kakushin.io LTD

Diagram of the MQTT publish/subscribe architecture: three publisher devices each sending a message on topic sensors/temp into a central broker, which fans the messages back out to three subscribers

Most of what I build assumes the network is basically there. WebRTC, the transport underneath a decade of real-time work, spends its whole design budget on one bet: a connection exists, and the job is to make it fast and keep it alive. One of my first Node.js projects, a university semester before any of that, assumed the opposite. I built a small MQTT broker and a publisher/subscriber IoT stack — protocols designed for the case WebRTC simply does not tolerate: a link that isn't there yet, drops mid-session, or comes back an hour later with no explanation.

Built for a bad connection, on purpose

MQTT dates to 1999, designed at IBM for monitoring oil pipelines over satellite links — expensive per byte, high-latency, and unreliable in ways a data-centre network never is. Every design choice reads as a direct answer to that link. The fixed header can be as small as two bytes. The protocol is binary, not text, because text costs bytes you cannot spend twice a decade later on a cellular IoT device with the same constraint. It runs over TCP, but it does not trust the TCP session to mean what a session normally means — the protocol is built assuming the connection itself is the unreliable part, not an implementation detail underneath a reliable one.

The idea that actually matters: nobody has to know who's listening

The architecture is publish/subscribe, and the useful part isn't the jargon, it's what it removes. A device that publishes a topic — sensors/room4/temp — does not know or care whether zero, one, or forty things are subscribed to it. It talks to exactly one thing: the broker. That collapses the connection topology from N devices needing to know about each other, which does not scale, to N devices each holding one connection to a broker, which does. The broker is the single piece of infrastructure that has to exist for any of it to work, and deciding where that piece physically sits — on the device network, at a gateway, in the cloud — is the same placement question I wrote about with fog computing: the broker is exactly the kind of thing a fog layer is for.

Three answers to "what if the message doesn't arrive"

MQTT's QoS levels are a dial, not a fixed guarantee, and the dial exists because the SCADA links it was built for drop messages routinely. QoS 0 is fire-and-forget: send it, don't check. QoS 1 guarantees at-least-once delivery via acknowledgement and retry, which means a subscriber has to handle duplicates — the retry itself can't know whether the first copy arrived. QoS 2 adds a second handshake to guarantee exactly-once, at the cost of a slower round trip. Nothing here is free; the protocol just makes you choose which failure you can tolerate instead of pretending none will happen.

Two mechanisms for a device that goes quiet

Two features exist specifically because "did that device disconnect on purpose, or did the link just die" is a real, frequently unanswerable question on the kind of network MQTT targets.

Retained messages let the broker hold the last message published to a topic and hand it to anyone who subscribes later, so a dashboard that connects five minutes after a sensor last reported still gets its current state instead of silence. Last Will and Testament lets a client register a message when it connects that the broker publishes on its behalf if it disappears without a clean disconnect — the closest the protocol gets to a device announcing its own failure after the fact.

Neither has a real equivalent in WebRTC, and that is the point: WebRTC's ICE and connection-state machinery assumes a peer that is actively trying to stay reachable and tells you the moment it isn't. MQTT assumes silence is the normal case and builds a story for what to do about it.

What building the broker taught me

The naive version of a broker is a hash map from topic to a list of subscriber connections — that part takes an afternoon. What the semester project actually forced me to confront was session state: what a broker owes a client across a gap it wasn't there for. Does a QoS 1 message sent while a client was offline get redelivered on reconnect? What happens to a QoS 2 message stuck mid-handshake when the connection drops? None of that is in the "publish/subscribe" pitch. All of it is where a broker actually lives or dies, and it is the same category of problem — state ownership across an unreliable link — that shows up in every real-time system I have built since, WebRTC included.

Two assumptions, one systems question

WebRTC optimises for a connection that exists and needs to be fast. MQTT optimises for a connection that might not exist at all, and asks you to decide in advance what happens if it doesn't. Neither assumption is wrong; they're for different links. What I didn't expect, building a toy broker years before either mattered professionally, is how often a single system now needs both — a device reporting telemetry over MQTT to whatever sits at the fog layer, and a live audio or video path running WebRTC alongside it. The network isn't a wire. It's an assumption, and you can tell a great deal about what a protocol is for by which assumption it was built to survive.


Related: the placement problem fog computing solved before "edge AI" had a name.