MQTT (Message Queuing Telemetry Transport) is a lightweight publish-subscribe messaging protocol designed for constrained devices and low-bandwidth, high-latency, or unreliable networks. A central broker receives messages from publishers and routes them to subscribers based on topic strings.
In practice
MQTT is widely used in IoT and embedded telemetry applications where devices need to send sensor data or receive commands over TCP/IP without the overhead of HTTP. A temperature sensor node, for example, might publish readings to a topic like `sensors/building3/temp` every 30 seconds; a dashboard or control system subscribes to that topic and receives updates automatically. The broker -- commonly Mosquitto, HiveMQ, or a cloud service such as AWS IoT Core -- handles routing, so individual devices do not need to know about each other directly, though they must share topic conventions and broker address configuration.
On resource-constrained MCUs with Wi-Fi or Ethernet peripherals (such as the ESP32 or Raspberry Pi Pico W), MQTT client libraries like the Mongoose networking library, PicoMQTT, or lwMQTT run on top of a TCP stack and typically consume a few kilobytes of RAM. The protocol's minimal fixed header (as small as 2 bytes) makes it practical even on parts with tens of kilobytes of RAM; payload compression is not part of the MQTT standard but can be added at the application layer if needed. The blog posts "When a Mongoose met a MicroPython, part II" and "Picowoose: The Raspberry Pi Pico-W meets Mongoose" demonstrate this kind of integration on small embedded targets.
A key operational concept is Quality of Service (QoS). MQTT defines three levels: QoS 0 (fire and forget, no acknowledgment), QoS 1 (at least once delivery, requires acknowledgment), and QoS 2 (exactly once, four-part handshake). On embedded targets, QoS 0 is common because it eliminates retransmission state, but it means dropped packets are silently lost. QoS 1 and 2 require the client to persist unacknowledged messages, which adds RAM and flash requirements that may be significant on very small devices.
Common pitfalls include failing to handle broker disconnections gracefully -- TCP connections drop silently on lossy links, and the client must detect the loss (via MQTT keepalive PINGREQ/PINGRESP or a TCP timeout) and reconnect. The Last Will and Testament (LWT) feature lets the broker publish a predefined message on a client's behalf if the connection drops unexpectedly, which is useful for presence detection. Developers should also be careful with topic namespace design early in a project; flat or poorly structured topic trees become difficult to manage as device counts grow.
Frequently asked
What runs the broker, and does it need to be on a separate server?
Typically yes -- the broker is a separate networked process, not something that runs on the embedded device itself. Common choices are Mosquitto (open source, runs on a Raspberry Pi or Linux server), HiveMQ, or cloud brokers like AWS IoT Core, Azure IoT Hub, and Google Cloud IoT. Some highly integrated designs embed a minimal broker on a gateway
MCU with enough resources (e.g., a Linux-class SoC), but that is uncommon for typical sensor nodes.
How does MQTT compare to HTTP for sending sensor data?
HTTP follows a request-response model: the client opens a connection, sends a request, waits for a response, and closes the connection. This per-message overhead is significant for frequent small updates. MQTT maintains a persistent TCP connection and sends minimal framing per message, making it more efficient for many small, frequent payloads. HTTP is simpler to firewall and debug, and HTTPS is more universally supported in corporate environments, so the right choice depends on infrastructure constraints.
What is a retained message and when is it useful?
A retained message is the last message published to a topic, stored by the broker. When a new subscriber connects and subscribes to that topic, the broker immediately delivers the retained message without waiting for the next publish event. This is useful for device state topics (e.g., current setpoint, firmware version) where a new subscriber should get the current value right away rather than waiting an unknown amount of time for the next update.
Does MQTT require TLS, and can small MCUs support it?
The base MQTT spec does not mandate
TLS; plaintext TCP on port 1883 is valid. TLS on port 8883 is strongly recommended for anything beyond a local network. TLS support on small MCUs is achievable -- libraries like mbedTLS and wolfSSL are designed for embedded use -- but TLS handshakes consume significant
RAM (often 20-80 KB depending on cipher suite and library configuration) and add
latency. Very small parts (under 32 KB RAM) may struggle; mid-range MCUs like the ESP32 or STM32 with an
Ethernet PHY handle it routinely.
What is the maximum message size in MQTT?
MQTT 3.1.1 encodes packet size using a 4-byte variable-length Remaining Length field, giving a theoretical maximum packet size of 268,435,455 bytes (roughly 256 MB); note this is a limit on the total packet, not the payload alone. In practice, embedded clients and brokers impose much lower limits -- many libraries default to a few kilobytes -- because buffering large payloads in
RAM is impractical on constrained devices. For large data transfers, it is common to send a URI or a smaller structured payload (JSON or CBOR) and fetch bulk data separately.
Differentiators vs similar concepts
MQTT is often compared to AMQP and
CoAP. AMQP is a heavier broker-based protocol common in enterprise messaging; it offers richer routing semantics but has substantially more overhead, making it rare on
MCU-class devices. CoAP (Constrained Application Protocol) is also designed for constrained devices but follows a request-response model similar to HTTP and is typically carried over
UDP rather than TCP, making it better suited for very lossy networks where a persistent connection is impractical. MQTT-SN (MQTT for Sensor Networks) is a variant of MQTT adapted for non-TCP transports like UDP,
Zigbee, or Bluetooth, using numeric topic IDs instead of strings to reduce packet size; unlike standard MQTT, which always runs over TCP, MQTT-SN is designed specifically for these alternative transports.