[{"data":1,"prerenderedAt":449},["ShallowReactive",2],{"blog-mqtt-protocol-guide-for-iot":3},{"id":4,"title":5,"body":6,"category":436,"date":437,"description":438,"extension":439,"meta":440,"navigation":441,"path":442,"readingTime":443,"seo":444,"stem":445,"tool":446,"updated":447,"__hash__":448},"blog\u002Fblog\u002Fmqtt-protocol-guide-for-iot.md","MQTT Protocol Guide for IoT",{"type":7,"value":8,"toc":416},"minimark",[9,13,16,21,24,59,63,70,100,103,114,117,123,133,138,173,177,180,184,187,193,197,200,205,209,212,217,224,228,231,237,240,244,247,253,260,264,278,282,285,323,327,403,407],[10,11,12],"p",{},"MQTT (Message Queuing Telemetry Transport) is the dominant messaging protocol for IoT (Internet of Things). It connects billions of devices — from industrial sensors and smart home devices to fleet tracking systems and medical monitors. If you are building anything that involves devices communicating over a network, you need to understand MQTT.",[10,14,15],{},"This guide covers the protocol fundamentals, quality of service levels, and practical patterns.",[17,18,20],"h2",{"id":19},"why-mqtt","Why MQTT?",[10,22,23],{},"MQTT was designed in 1999 for oil pipeline telemetry over satellite links — a scenario with low bandwidth, unreliable connections, and constrained devices. These design constraints produced a protocol that is:",[25,26,27,35,41,47,53],"ul",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"Lightweight"," — minimal packet overhead (as little as 2 bytes for a header)",[28,36,37,40],{},[31,38,39],{},"Publish\u002Fsubscribe"," — decouples senders and receivers",[28,42,43,46],{},[31,44,45],{},"Reliable"," — three QoS levels for different reliability needs",[28,48,49,52],{},[31,50,51],{},"Bidirectional"," — both devices and servers can publish and subscribe",[28,54,55,58],{},[31,56,57],{},"Battery-friendly"," — supports long idle periods with keepalive pings",[17,60,62],{"id":61},"publishsubscribe-model","Publish\u002FSubscribe Model",[10,64,65,66,69],{},"Unlike HTTP (request\u002Fresponse), MQTT uses a publish\u002Fsubscribe model with a central ",[31,67,68],{},"broker",":",[71,72,73,88,94],"ol",{},[28,74,75,78,79,82,83,87],{},[31,76,77],{},"Publishers"," send messages to ",[31,80,81],{},"topics"," (e.g., ",[84,85,86],"code",{},"sensors\u002Ftemperature\u002Froom1",")",[28,89,90,91,93],{},"The ",[31,92,68],{}," receives messages and routes them to subscribers",[28,95,96,99],{},[31,97,98],{},"Subscribers"," register interest in topics (with optional wildcards)",[10,101,102],{},"Publishers and subscribers never communicate directly. The broker handles all routing, which means:",[25,104,105,108,111],{},[28,106,107],{},"Publishers do not need to know who is listening",[28,109,110],{},"Subscribers do not need to know who is sending",[28,112,113],{},"Devices can go offline and reconnect without breaking the system",[17,115,116],{"id":81},"Topics",[10,118,119,120,69],{},"MQTT topics are hierarchical strings separated by ",[84,121,122],{},"\u002F",[124,125,130],"pre",{"className":126,"code":128,"language":129},[127],"language-text","home\u002Flivingroom\u002Ftemperature\nhome\u002Flivingroom\u002Fhumidity\nhome\u002Fbedroom\u002Ftemperature\nfactory\u002Fline1\u002Fmachine3\u002Fstatus\n","text",[84,131,128],{"__ignoreMap":132},"",[134,135,137],"h3",{"id":136},"wildcards-for-subscribers-only","Wildcards (for subscribers only)",[25,139,140,157,170],{},[28,141,142,145,146,149,150,153,154],{},[84,143,144],{},"+"," matches exactly one level: ",[84,147,148],{},"home\u002F+\u002Ftemperature"," matches ",[84,151,152],{},"home\u002Flivingroom\u002Ftemperature"," and ",[84,155,156],{},"home\u002Fbedroom\u002Ftemperature",[28,158,159,162,163,166,167],{},[84,160,161],{},"#"," matches any number of levels: ",[84,164,165],{},"home\u002F#"," matches everything under ",[84,168,169],{},"home\u002F",[28,171,172],{},"You cannot publish to a wildcard topic — only subscribe",[17,174,176],{"id":175},"quality-of-service-qos","Quality of Service (QoS)",[10,178,179],{},"MQTT defines three QoS levels:",[134,181,183],{"id":182},"qos-0-at-most-once","QoS 0: At Most Once",[10,185,186],{},"Fire and forget. The message is delivered once with no confirmation. It may be lost if the connection drops.",[10,188,189,192],{},[31,190,191],{},"Use for:"," High-frequency sensor data where individual lost readings are acceptable (temperature every second).",[134,194,196],{"id":195},"qos-1-at-least-once","QoS 1: At Least Once",[10,198,199],{},"The broker acknowledges receipt. If no acknowledgment arrives, the publisher resends. This may cause duplicates.",[10,201,202,204],{},[31,203,191],{}," Important events that must be delivered, where duplicates can be handled idempotently (door opened, alarm triggered).",[134,206,208],{"id":207},"qos-2-exactly-once","QoS 2: Exactly Once",[10,210,211],{},"A four-step handshake ensures the message is delivered exactly once. Highest overhead but no duplicates and no loss.",[10,213,214,216],{},[31,215,191],{}," Critical commands where duplicates would cause problems (billing events, actuator commands).",[10,218,219,220,223],{},"The effective QoS is the ",[31,221,222],{},"minimum"," of the publisher's QoS and the subscriber's QoS. If you publish at QoS 2 but the subscriber subscribed at QoS 0, the delivery is QoS 0.",[17,225,227],{"id":226},"retained-messages","Retained Messages",[10,229,230],{},"A retained message is stored by the broker and sent immediately to any new subscriber on that topic. This is useful for \"last known value\" patterns:",[124,232,235],{"className":233,"code":234,"language":129},[127],"Topic: sensors\u002Fbattery\u002Flevel\nPayload: \"87\"\nRetained: true\n",[84,236,234],{"__ignoreMap":132},[10,238,239],{},"When a new subscriber connects, it immediately receives the last battery level without waiting for the next publish. Only one retained message is stored per topic — a new retained message replaces the old one.",[17,241,243],{"id":242},"last-will-and-testament-lwt","Last Will and Testament (LWT)",[10,245,246],{},"When a client connects, it can register a \"last will\" message — a message the broker publishes if the client disconnects unexpectedly (without a proper DISCONNECT packet):",[124,248,251],{"className":249,"code":250,"language":129},[127],"Will Topic: devices\u002Fsensor42\u002Fstatus\nWill Payload: \"offline\"\nWill QoS: 1\nWill Retain: true\n",[84,252,250],{"__ignoreMap":132},[10,254,255,256,259],{},"Combined with a regular retained message on connect (",[84,257,258],{},"\"online\"","), this creates a reliable online\u002Foffline status indicator.",[17,261,263],{"id":262},"clean-session-vs-persistent-session","Clean Session vs Persistent Session",[25,265,266,272],{},[28,267,268,271],{},[31,269,270],{},"Clean session (true):"," The broker discards any previous session state. Subscriptions must be re-established on each connect. Default for most clients.",[28,273,274,277],{},[31,275,276],{},"Persistent session (false):"," The broker stores subscriptions and queued messages (QoS 1+) while the client is offline, delivering them on reconnect.",[17,279,281],{"id":280},"mqtt-50-features","MQTT 5.0 Features",[10,283,284],{},"MQTT 5.0 (released 2019) adds:",[25,286,287,293,299,305,311,317],{},[28,288,289,292],{},[31,290,291],{},"Reason codes"," on every acknowledgment",[28,294,295,298],{},[31,296,297],{},"Message expiry"," — messages can have a TTL",[28,300,301,304],{},[31,302,303],{},"Topic aliases"," — reduce per-message overhead for repeated topics",[28,306,307,310],{},[31,308,309],{},"Request\u002Fresponse"," pattern with response topics",[28,312,313,316],{},[31,314,315],{},"User properties"," — custom key-value metadata on messages",[28,318,319,322],{},[31,320,321],{},"Shared subscriptions"," — load balance messages across multiple subscribers",[17,324,326],{"id":325},"common-brokers","Common Brokers",[328,329,330,346],"table",{},[331,332,333],"thead",{},[334,335,336,340,343],"tr",{},[337,338,339],"th",{},"Broker",[337,341,342],{},"Type",[337,344,345],{},"Notes",[347,348,349,361,372,382,393],"tbody",{},[334,350,351,355,358],{},[352,353,354],"td",{},"Mosquitto",[352,356,357],{},"Open source",[352,359,360],{},"Lightweight, standard reference implementation",[334,362,363,366,369],{},[352,364,365],{},"HiveMQ",[352,367,368],{},"Commercial",[352,370,371],{},"Enterprise features, clustering",[334,373,374,377,379],{},[352,375,376],{},"EMQX",[352,378,357],{},[352,380,381],{},"High performance, Erlang-based",[334,383,384,387,390],{},[352,385,386],{},"AWS IoT Core",[352,388,389],{},"Cloud",[352,391,392],{},"Managed, integrates with AWS services",[334,394,395,398,400],{},[352,396,397],{},"Azure IoT Hub",[352,399,389],{},[352,401,402],{},"Managed, integrates with Azure services",[17,404,406],{"id":405},"try-it","Try It",[10,408,409,410,415],{},"Connect to any MQTT broker over secure WebSockets with ",[411,412,414],"a",{"href":413},"\u002Ftools\u002Fmqtt-client","StackCache MQTT Client",". Subscribe to topics, publish messages, and inspect payloads in real time — directly from your browser with no install.",{"title":132,"searchDepth":417,"depth":417,"links":418},2,[419,420,421,425,430,431,432,433,434,435],{"id":19,"depth":417,"text":20},{"id":61,"depth":417,"text":62},{"id":81,"depth":417,"text":116,"children":422},[423],{"id":136,"depth":424,"text":137},3,{"id":175,"depth":417,"text":176,"children":426},[427,428,429],{"id":182,"depth":424,"text":183},{"id":195,"depth":424,"text":196},{"id":207,"depth":424,"text":208},{"id":226,"depth":417,"text":227},{"id":242,"depth":417,"text":243},{"id":262,"depth":417,"text":263},{"id":280,"depth":417,"text":281},{"id":325,"depth":417,"text":326},{"id":405,"depth":417,"text":406},"IoT","2026-09-08","Learn the MQTT protocol for IoT: publish\u002Fsubscribe messaging, QoS levels, retained messages, and last will. Includes broker setup and practical examples.","md",{},true,"\u002Fblog\u002Fmqtt-protocol-guide-for-iot",8,{"title":5,"description":438},"blog\u002Fmqtt-protocol-guide-for-iot","mqtt-client",null,"bk27r9fK0V5WiF5mtDDCH07iTSlp1Ie_BhPizQEV8xE",1788868139495]