MQTT is a lightweight publish and subscribe messaging protocol. Devices and applications connect to one server, the broker, and send messages to named topics such as site/dub01/mdb1/main-incomer. Any client that has subscribed to that topic receives the message from the broker. Publishers and subscribers never address each other, so a meter, a dashboard and a cloud platform can share data without knowing about each other. MQTT runs over TCP on port 1883, or over TLS on port 8883, and its fixed header is only two bytes. Because every device connects outwards to the broker and any number of systems can subscribe to the same data, it has become the most common protocol for sending sensor and meter telemetry over the internet.
How MQTT works
| Part | What it does | Example |
|---|---|---|
| Broker | Accepts connections, checks permissions and forwards each message to matching subscribers | Eclipse Mosquitto on a server, or a cloud IoT service |
| Client | Any device or application that connects to the broker, to publish, subscribe or both | A Gateway, a dashboard, a database writer |
| Topic | A text address with levels separated by / | site/dub01/mdb1/main-incomer |
| Message | A topic, a payload of up to 256 MB and a few flags | A JSON object with the readings |
| Subscription | A topic filter, with optional wildcards | site/dub01/# |
| QoS | The acknowledgement level on each hop | 0, 1 or 2 |
| Session | The broker's memory of a client's subscriptions and undelivered messages | Kept across a reconnect if the client asks for it |
A client opens a TCP connection to the broker and sends CONNECT with its client identifier, credentials and a keep-alive interval. The broker answers CONNACK. A publisher then sends PUBLISH packets; a subscriber sends SUBSCRIBE with one or more topic filters, and the broker sends it every matching PUBLISH from then on. If no packet passes within the keep-alive interval, the client sends PINGREQ, and the broker closes a connection that stays silent for one and a half times the interval.
Because every client makes an outgoing connection to the broker, a site Gateway needs no open inbound port. This is the main practical reason MQTT replaced polled protocols for sending data off site.
Topics and wildcards
Topics are case-sensitive strings. A client does not create a topic; it publishes to it, and the broker routes the message to every subscription that matches. A subscription can use two wildcards:
| Filter | Matches | Does not match |
|---|---|---|
site/dub01/mdb1/+ | site/dub01/mdb1/main-incomer, site/dub01/mdb1/chiller-2 | site/dub01/mdb1/chiller-2/alarm |
site/dub01/# | Every topic under site/dub01, at any depth | site/cork02/mdb1/main-incomer |
site/+/mdb1/main-incomer | That meter on every site | Other meters |
+ matches one level and # matches the rest of the tree, so it must come last. Topics that start with $ are reserved for the broker, such as $SYS/ for broker statistics, and a filter that starts with a wildcard does not match them.
Plan the topic tree before the first device publishes, because every subscriber and access rule depends on it. A good tree runs from the widest scope to the narrowest (organisation, site, panel, device, then the type of message), keeps one device in one place, and leaves out values that change, such as a reading, a timestamp or a session number. Separate telemetry, status and command topics, so that write permission can be given only where it is needed.
QoS, retained messages and last will
MQTT has three delivery levels. They apply to one hop at a time: publisher to broker, and broker to each subscriber.
| QoS | Delivery | Packets on one hop | Typical use |
|---|---|---|---|
| 0 | At most once | PUBLISH | Frequent readings where a lost one is soon replaced |
| 1 | At least once, duplicates possible | PUBLISH, PUBACK | Meter readings and events that must arrive |
| 2 | Exactly once on that hop | PUBLISH, PUBREC, PUBREL, PUBCOMP | Rare; costs four packets per message |
A retained message is kept by the broker as the last value of its topic and sent to every new subscriber at once, which suits a device status but can deliver a stale reading. A last will is a message the broker publishes for a client when its connection drops without a clean DISCONNECT, which is how a subscriber learns that a Gateway has gone offline. The MQTT QoS and retained messages guide covers both in detail, with message expiry and persistent sessions.
MQTT ports and security
| Port | Transport | Use |
|---|---|---|
| 1883 | TCP | MQTT without encryption: only on a closed local network |
| 8883 | TLS over TCP | MQTTS: the normal choice over the internet or a shared network |
| 443 (or another) | WebSocket over TLS | Browsers, and networks that allow only HTTPS |
MQTT itself has a username and password field and nothing else. Encryption, server identity and client certificates come from TLS, and access control comes from the broker's rules on which client may publish or subscribe to which topics. The MQTTS guide explains certificates, server name checks and how to test a TLS connection from the command line.
MQTT 3.1.1 vs MQTT 5
MQTT was designed in 1999 for pipeline telemetry over satellite links. OASIS published MQTT 3.1.1 as a standard in 2014, which became ISO/IEC 20922 in 2016, and MQTT 5.0 in 2019. Most brokers support both, and many devices still speak only 3.1.1.
| MQTT 3.1.1 | MQTT 5.0 | |
|---|---|---|
| Acknowledgements | Success or a few CONNACK codes | A reason code on every acknowledgement, including refusals |
| Session | Clean session on or off | Session expiry interval |
| Message lifetime | None | Message expiry interval |
| Metadata | None | User properties, content type, payload format indicator |
| Load sharing | Broker-specific | Shared subscriptions ($share/group/topic) |
| Bandwidth | Full topic every time | Topic aliases replace a long topic with a number |
| Request and response | By convention | Response topic and correlation data |
| Flow control | None | Receive maximum and maximum packet size |
For telemetry, the most useful MQTT 5 features are reason codes, because a client can see that the broker refused a message, and message expiry, because a command delayed by an outage is discarded instead of executed late.
Payloads: JSON, Sparkplug B and the data contract
MQTT carries bytes and says nothing about what they mean. Most energy platforms expect JSON, for example:
{"ts":"2026-10-28T09:15:00Z","kW":184.2,"kWh":1532871.4,"V1":231.4,"PF":0.94,"q":"good"}The topic says which meter it is; the payload carries the measurement time, the values and a quality flag. The units and the meaning of each key have to be written down and agreed with every subscriber: kW or W, import or net energy, the meter's time or the time the Gateway received it. That agreement, not MQTT support, is what makes two systems work together. The interoperability guide lists what a data contract should fix, and the source time and arrival time guide explains why the measurement time belongs in the payload.
Sparkplug B, an Eclipse Foundation specification common in industrial systems, fixes the contract instead. Topics follow spBv1.0/<group>/<message type>/<edge node>/<device>, payloads are binary Protocol Buffers, and every edge node publishes a birth certificate listing its metrics and a death certificate (sent through the last will) when it disconnects. A subscriber can then discover devices and mark data as stale without any custom agreement, at the cost of a binary format that needs a Sparkplug-aware client to read.
Worked example: how much data does MQTT telemetry use?
Fifty meters each publish the JSON message above every 10 seconds at QoS 1. The payload is 88 bytes and the topic 28 bytes, so each PUBLISH packet is about 122 bytes. TLS adds about 22 bytes per record and TCP and IP about 52 bytes per segment, so each message is roughly 200 bytes on the wire.
| One message per meter | One message per site | |
|---|---|---|
| Messages per day | 50 × 8,640 = 432,000 | 8,640 |
| Size of each message on the wire | about 200 bytes | about 3,900 bytes (50 readings) |
| Data sent per day | about 86 MB | about 34 MB |
| Data per month | about 2.6 GB | about 1 GB |
The per-site message carries the 50 readings as one JSON array of about 3,650 bytes (about 73 bytes per meter, with one timestamp for the whole message) plus the topic and headers, which TCP splits into three segments.
The PUBACKs coming back add a further 30 MB or so a day in the first case. On a fixed line none of this matters; on a cellular SIM it decides the data plan. Batching the readings of one site into one message, or sending changes only, cuts the overhead. The interval demand calculator helps to choose an interval that still answers the question the data is for.
MQTT compared with other protocols
| MQTT | HTTP (REST) | Modbus TCP | OPC UA | |
|---|---|---|---|---|
| Pattern | Publish and subscribe through a broker | Request and response | Request and response, client polls | Client and server, with subscriptions; also a publish and subscribe mode |
| Who connects | Every client connects out to the broker | Client to server | Client to each device | Client to each server |
| Data model | None: the payload is free | None: defined by the API | Numbered registers | Typed nodes with units and status |
| Typical place | Site to cloud, device to platform | Occasional uploads, web APIs | Meters and controllers on site | Plant systems and SCADA |
MQTT is usually the link from a site to a platform, while Modbus, BACnet and OPC UA read the devices on the site. The OPC UA vs Modbus vs MQTT guide compares them for industrial projects, and what is Modbus explains the polled side.
MQTT with EpiSensor
Edge on the ZGW-20 Gateway reads Zigbee, Modbus, BACnet and LoRaWAN devices on site, records each reading with its measurement time, and publishes to a platform's broker as an MQTT client, normally over MQTTS on port 8883 with a client certificate. It publishes at QoS 1 and keeps failed deliveries in a local queue, replaying them with their original timestamps when the broker returns. The topics and payload follow the platform's contract, and Connect Edge to your platform shows the ways Edge sends data out.
Common questions
What is MQTT used for?
MQTT carries small, frequent messages between devices and applications: sensor and meter readings, status changes and commands. It is used in building and energy monitoring, industrial telemetry, vehicle tracking and home automation, because one connection per device is enough and the protocol overhead is a few bytes per message.
What is an MQTT broker?
The broker is the server at the centre of MQTT. Clients connect to it, publish messages to topics and subscribe to topics. The broker checks each client's permissions, keeps sessions and retained messages, and forwards each message to every client with a matching subscription. Eclipse Mosquitto, EMQX and HiveMQ are common brokers, and the large cloud IoT services include one.
What port does MQTT use?
TCP port 1883 for MQTT without encryption and TCP port 8883 for MQTT over TLS (MQTTS). Both are registered with IANA. MQTT over WebSockets has no fixed port; it often runs on 443 behind a web server, which helps where a firewall allows only HTTPS.
Is MQTT TCP or UDP?
MQTT runs over TCP, or over another transport that delivers bytes in order without loss, such as TLS or WebSockets. A separate protocol, MQTT-SN, is designed for sensor networks and can run over UDP.
What is the difference between MQTT and HTTP?
HTTP is request and response: a client asks a server and waits for an answer, and a new request is needed for each piece of data. MQTT keeps one connection open and the broker pushes each message to subscribers as it arrives. For frequent small readings MQTT uses less bandwidth and delivers changes sooner; HTTP is simpler for occasional uploads and for systems that only expose a REST API.
What is the difference between MQTT 3.1.1 and MQTT 5?
MQTT 5 keeps the same model and adds reason codes on every acknowledgement, message and session expiry, user properties, shared subscriptions, topic aliases and request and response topics. A broker that supports MQTT 5 still accepts MQTT 3.1.1 clients, so both often run side by side.
What is Sparkplug B?
Sparkplug is an Eclipse Foundation specification that adds a fixed topic namespace, a binary payload and birth and death messages on top of MQTT. A subscriber can then discover the metrics of each edge node and know when its data is stale. MQTT itself defines none of these.