MQTT vs Sparkplug B: What's the Difference? (2026 Guide)
MQTT vs Sparkplug B compared — topic structure, JSON vs Protobuf payloads, state management, and when controls engineers should use plain MQTT or Sparkplug.
The single most common question controls engineers ask when they start building IIoT connectivity is this: if MQTT already works, why does Sparkplug B exist? The short answer is that plain MQTT is a transport layer — it delivers bytes between a publisher and a subscriber, but says nothing about what those bytes mean, how topics should be named, or what happens when a device drops off the network. Sparkplug B is an application-layer specification built on top of MQTT that answers all three questions.
Understanding exactly where the boundary sits — and which side of it your project belongs on — will save you weeks of rework.
Quick Comparison: MQTT vs Sparkplug B at a Glance
| Feature | Plain MQTT | Sparkplug B |
|---|---|---|
| Standard body | OASIS (MQTT 3.1.1 / 5.0) | Eclipse Foundation (spBv1.0) |
| Topic structure | Free-form, user-defined | Enforced: spBv1.0/group/DDATA/edge/device |
| Payload format | Any bytes (JSON, CSV, hex, etc.) | Google Protocol Buffers (Protobuf) only |
| Payload size | Depends on encoding chosen | ~40–70% smaller than equivalent JSON |
| State management | Manual (LWT only) | Built-in Birth/Death certificates |
| Metric-level subscribe | Yes — one topic per tag possible | No — full payload per publish |
| Broker requirement | Any MQTT broker | Any MQTT broker (no broker modification needed) |
| Host application | Not defined | SCADA/host node role is specified |
| Primary IIoT use case | Custom, lightweight telemetry | Unified Namespace (UNS), SCADA integration |
| Vendor ecosystem | Universal | Ignition, HiveMQ, EMQX, Cirrus Link |
Plain MQTT in 60 Seconds
MQTT (Message Queuing Telemetry Transport) is a publish-subscribe messaging protocol designed for low-bandwidth, high-latency, or unreliable networks. A device (publisher) connects to a broker and publishes a message to a topic string. Any connected client that has subscribed to that topic string receives the message. The broker never interprets the payload — it is opaque bytes from the broker's perspective.
The protocol guarantees delivery via three QoS levels:
- QoS 0 — fire and forget, no acknowledgement
- QoS 1 — at least once delivery, may duplicate
- QoS 2 — exactly once delivery, highest overhead
MQTT's built-in session persistence mechanism is the Last Will and Testament (LWT): a message the broker sends automatically if a client disconnects ungracefully. That is the extent of MQTT's native state management.
The protocol is defined by OASIS. MQTT 3.1.1 (ISO/IEC 20922) is the version most industrial devices support today. MQTT 5.0 adds useful features like user properties, message expiry, and reason codes, but device firmware support for 5.0 remains limited as of mid-2026.
For a deep dive into connecting PLCs over MQTT, see the IIoT PLC integration complete guide.
What Sparkplug B Adds
Sparkplug B (specification version spBv1.0, maintained by the Eclipse Foundation) is not a replacement for MQTT. It is an application-layer convention that rides on any standard MQTT 3.1.1 broker and defines three things plain MQTT deliberately leaves open:
- Topic namespace — a rigid, hierarchical naming scheme so every message has a known, machine-parseable address
- Payload encoding — Google Protocol Buffers (Protobuf) with a defined schema, so any host can decode any Sparkplug B message without out-of-band schema negotiation
- Session state model — Birth messages, Death messages, and a Primary Host Application concept that enables stateful, SCADA-grade session management
Sparkplug B was originally developed by Cirrus Link Solutions and donated to the Eclipse Foundation in 2016. It has since become the de-facto IIoT standard for Unified Namespace (UNS) architectures and is natively supported by Ignition (Inductive Automation), HiveMQ, EMQX, and most modern IIoT platforms.
To understand what is Sparkplug B in more depth — including the full UNS context and how the Primary Host Application role works — that companion article covers the specification detail.
Topic Structure Compared: Free-Form Chaos vs. spBv1.0
This is where the difference becomes most concrete for day-to-day integration work.
Plain MQTT topics
With plain MQTT, topic naming is entirely up to you. Common patterns in the wild:
factory/line1/plc01/temperature
sensors/+/pressure
plant/area-3/conveyor/#
Every project, every vendor, every integrator invents their own structure. A historian connecting to 40 different MQTT publishers needs 40 different topic-parsing configurations. Wildcard subscriptions (+, #) help but they do not provide semantic meaning.
Sparkplug B topics
Sparkplug B enforces this exact structure:
spBv1.0/<Group_ID>/<Message_Type>/<Edge_Node_ID>/<Device_ID>
Where <Message_Type> is one of:
NBIRTH/NDEATH— Edge Node birth and deathDBIRTH/DDEATH— Device birth and deathNDATA/DDATA— Node and device data updatesNCMD/DCMD— Commands from host to edge/deviceSTATE— Primary Host Application state
A real-world Sparkplug B topic looks like:
spBv1.0/PlantA/DDATA/ConveyorLine1/PLC_01
Any consuming system — historian, SCADA, digital twin — immediately knows from the topic alone: this is a data update (DDATA) from a device called PLC_01 on edge node ConveyorLine1 in the PlantA group. No side-channel configuration required.
Payload Comparison: JSON vs Protobuf
Plain MQTT with JSON
Most plain MQTT implementations use JSON because it is human-readable and easy to produce in any language or PLC scripting environment:
{
"timestamp": 1750000000123,
"temperature": 72.4,
"pressure": 14.7,
"motor_running": true,
"fault_code": 0
}
Byte count: ~92 bytes for this five-metric message. Readable, but verbose. Every field name is transmitted with every message, adding overhead that multiplies across thousands of messages per second on a busy plant floor.
Sparkplug B with Protobuf
The same five metrics encoded as a Sparkplug B DDATA Protobuf payload would serialize to approximately 30–40 bytes — roughly a 60% reduction. Field names are not transmitted; the schema is agreed upon at BIRTH time. Protobuf encoding is also significantly faster to serialize and deserialize than JSON parsing.
The Sparkplug B Protobuf schema defines a Payload message with a repeated Metric field. Each metric carries:
name(string, sent in BIRTH only, referenced by alias integer in DDATA)timestamp(uint64, milliseconds since epoch)datatype(uint32 enum — Int8 through Float, Boolean, String, DataSet, etc.)value(one of several typed fields)is_historical,is_transient,is_nullflags- Optional
metadataandproperties
The metric alias optimization is significant: after the BIRTH message establishes the name → alias mapping, subsequent DDATA messages only transmit the integer alias, not the full metric name string. For a PLC with 200 tags publishing at 1-second scan rates, this reduces payload sizes dramatically over a cellular or satellite uplink.
State Management: Birth and Death Certificates
This is the area where Sparkplug B provides the most value over raw MQTT, and it is the area most often underestimated until a project hits production.
The problem with MQTT LWT
MQTT's Last Will and Testament tells the broker: "if I disconnect ungracefully, publish this message to this topic." That gives you one bit of information — the device is gone. It tells you nothing about:
- What state the device was in before it dropped
- Whether the data in any retained messages is still valid
- Whether the broker itself restarted and lost session state
- Whether the consuming SCADA system restarted and needs a full resync
Sparkplug B Birth/Death certificates
Sparkplug B solves this with a defined session lifecycle:
NBIRTH (Node Birth) — published by an Edge Node immediately after connecting to the broker. Contains every metric the node will ever publish, with current values, data types, engineering units, and metadata. This is the "state of record" message. Any host that receives a NBIRTH gets a complete, timestamped snapshot of the node.
DBIRTH (Device Birth) — same concept, but for a logical device (e.g., a specific PLC or sensor) subordinate to an Edge Node.
NDEATH / DDEATH — published by the broker via LWT (pre-registered by the Edge Node at connect time) if the session drops without a clean disconnect. Contains a bdSeq (birth/death sequence number) that lets the host correlate the DEATH with the preceding BIRTH and know exactly which session ended.
NDATA / DDATA — published only when a metric value changes (report by exception). The host already has the full tag list from the BIRTH, so DDATA only needs to carry the changed metrics and their new values.
STATE — published by the Primary Host Application to announce whether it is online or offline. Edge Nodes watch for this message; if the Primary Host goes offline, they must hold their data and resync with a new BIRTH when the host comes back.
This birth-death-rebirth cycle means any consuming application — even one that joined the network after the device started publishing — can achieve a consistent, current state picture by receiving the most recent BIRTH message (which Sparkplug B implementations retain on the broker).
The Subscribe-to-Topic vs Whole-Payload Trade-off
This is a genuine Sparkplug B limitation that is rarely discussed in vendor documentation, and it matters for large-scale deployments.
With plain MQTT, you can publish each individual sensor reading to its own topic:
factory/line1/plc01/temperature → 72.4
factory/line1/plc01/pressure → 14.7
factory/line1/plc01/motor_running → true
A subscriber that only cares about temperature subscribes to factory/line1/plc01/temperature and receives only temperature messages. This is extremely efficient for consumers that need a small subset of a device's metrics.
With Sparkplug B, you cannot do this. A DDATA message is a single Protobuf payload containing all changed metrics for a device, published to a single topic (spBv1.0/Group/DDATA/EdgeNode/Device). If a consumer wants only temperature, it must still subscribe to the full DDATA topic, receive the full Protobuf payload, decode it, and filter out the metrics it cares about in application code.
For most IIoT architectures — especially UNS designs — this is a reasonable trade-off. The Protobuf compression and the structured topic namespace more than compensate. But for constrained subscribers (e.g., a microcontroller that needs only one value), plain MQTT with per-metric topics may be the correct choice.
For a detailed look at how this trade-off plays out against OPC UA's address space model, see the companion article Sparkplug vs OPC UA.
When to Use Plain MQTT vs Sparkplug B
Use plain MQTT when:
- Devices cannot produce Sparkplug B — older PLCs, microcontrollers, and embedded sensors that can only generate simple JSON or CSV over MQTT. Forcing Sparkplug B requires a gateway or significant firmware changes.
- You control both publisher and subscriber — a single custom application consuming from a single custom publisher has no interoperability requirement. The overhead of Sparkplug B's schema convention adds complexity with no benefit.
- You need per-metric subscriptions at the subscriber — constrained edge consumers that must filter at the broker rather than in application code.
- Protobuf tooling is not available on your platform — some legacy SCADA and historian products do not have Sparkplug B decode libraries. Plain JSON is more universally parseable.
- You are building a simple telemetry pipeline — sensor-to-cloud with a single application consuming the data, no SCADA integration, no shared data layer.
Use Sparkplug B when:
- You are building a Unified Namespace — the UNS pattern requires a consistent, self-describing data layer that every application can consume without custom integration. Sparkplug B's enforced topic structure and BIRTH-payload schema are purpose-built for this.
- All major vendors in your architecture support it — if your EPC, SCADA (Ignition), historian, and IIoT platform all speak Sparkplug B natively, the integration cost drops dramatically. Cirrus Link, HiveMQ, and EMQX all provide native Sparkplug B support.
- You need guaranteed state consistency — the Birth/Death certificate mechanism gives consuming applications a reliable way to know whether their view of device state is current. This matters for SCADA, alarming, and digital twin applications.
- Bandwidth is constrained — Protobuf payloads are significantly smaller than JSON. On cellular uplinks, satellite, or LPWAN backhaul, this directly reduces operating costs.
- You want report-by-exception at scale — Sparkplug B's DDATA model only publishes changed metrics, combined with the BIRTH-established tag list, efficiently implements RBE without requiring individual per-tag topics.
For background on the PLC communication protocols that sit below the MQTT layer — including Ethernet/IP, Modbus TCP, and PROFINET — see the full protocols reference.
Do You Need Ignition or HiveMQ?
A common misconception is that Sparkplug B requires a specific broker or platform. It does not. Sparkplug B runs on any standard MQTT 3.1.1 broker — Mosquitto, VerneMQ, EMQX, HiveMQ — without modification. The broker never inspects the Protobuf payload; it simply routes messages by topic string.
What specific platforms provide is not broker-level support but application-level Sparkplug awareness:
Ignition (Inductive Automation) — the MQTT Engine and MQTT Transmission modules natively understand Sparkplug B's BIRTH/DEATH lifecycle. Ignition automatically creates and manages tag structures from BIRTH payloads without manual tag configuration. This is the most widely deployed Sparkplug B host application in industrial environments.
HiveMQ — offers a Sparkplug B extension that provides broker-side awareness of Birth/Death state, enabling features like Sparkplug-aware retained message management and monitoring dashboards that understand device online/offline state.
EMQX — provides a Sparkplug B codec plugin and dashboard integration for visualizing Sparkplug B session state.
Cirrus Link MQTT modules for Ignition — the original Sparkplug B implementation. Still widely deployed.
Eclipse Tahu — the reference Sparkplug B implementation library, available for Java, Python, C, and C++. If your platform lacks native support, Tahu provides the Protobuf encode/decode layer.
For smaller deployments or custom integrations, Eclipse Mosquitto with Eclipse Tahu on the consuming side is a fully capable, zero-license Sparkplug B stack.
For context on where Sparkplug B and OPC UA overlap in enterprise IIoT architectures, the OPC UA complete guide covers the OPC UA PubSub model, which is an alternative standard addressing similar use cases.
Side-by-Side: A Real BIRTH + DDATA Sequence
This is what an actual Sparkplug B session looks like for a single PLC with three tags. The Protobuf is shown here in its human-readable JSON equivalent for clarity — over the wire, this is binary-encoded Protobuf.
Topic: spBv1.0/PlantA/DBIRTH/ConveyorLine1/PLC_01
{
"timestamp": 1750000000000,
"metrics": [
{
"name": "conveyor/speed_rpm",
"alias": 1,
"timestamp": 1750000000000,
"datatype": 10,
"float_value": 45.2
},
{
"name": "conveyor/motor_running",
"alias": 2,
"timestamp": 1750000000000,
"datatype": 11,
"boolean_value": true
},
{
"name": "conveyor/fault_active",
"alias": 3,
"timestamp": 1750000000000,
"datatype": 11,
"boolean_value": false
}
],
"seq": 0,
"bdSeq": 12
}
After the BIRTH, the host knows the tag list and the alias mapping. Now 30 seconds later, the motor stops and a fault activates. Only two metrics changed, so DDATA carries only those two:
Topic: spBv1.0/PlantA/DDATA/ConveyorLine1/PLC_01
{
"timestamp": 1750000030000,
"metrics": [
{
"alias": 2,
"timestamp": 1750000030000,
"datatype": 11,
"boolean_value": false
},
{
"alias": 3,
"timestamp": 1750000030000,
"datatype": 11,
"boolean_value": true
}
],
"seq": 1
}
Notice: alias integers replace the full metric names in DDATA. The binary Protobuf encoding of this DDATA payload is approximately 28 bytes. An equivalent JSON message with full field names would be roughly 180 bytes — a 6x size difference. At 1,000 DDATA messages per second across a plant, that difference matters.
Frequently Asked Questions
What is the difference between MQTT and Sparkplug B?
MQTT is a lightweight publish-subscribe messaging protocol that transports arbitrary byte payloads between publishers and subscribers via a broker. It defines how messages are delivered, but not what topics should be named or what the payload should contain. Sparkplug B is an application-layer specification built on top of MQTT that enforces a specific topic namespace (spBv1.0/group/type/edge/device), mandates Google Protocol Buffers as the payload encoding, and defines a Birth/Death certificate mechanism for stateful session management. Every Sparkplug B message is an MQTT message, but most MQTT messages are not Sparkplug B.
Is Sparkplug B better than MQTT?
Neither is universally better — they solve different problems. Plain MQTT is simpler, more flexible, and compatible with every device and platform that supports MQTT. Sparkplug B is more structured, more interoperable, and provides built-in state management that MQTT alone lacks. Sparkplug B is better when you need a Unified Namespace where multiple applications share the same data layer without custom integration work. Plain MQTT is better for point-to-point telemetry, constrained devices that cannot generate Protobuf payloads, or any use case where the structure Sparkplug B enforces adds more complexity than it removes.
Do you need Sparkplug B for IIoT?
No. Many successful IIoT deployments use plain MQTT with JSON payloads. Sparkplug B becomes highly valuable — often essential — when you are building a Unified Namespace architecture, integrating with Ignition SCADA, or connecting many heterogeneous devices that need to be consumed by multiple applications without custom per-source integration. If you have a single data source and a single consuming application, plain MQTT is almost always simpler and sufficient.
What broker works with Sparkplug B?
Any standard MQTT 3.1.1 broker works with Sparkplug B — including Eclipse Mosquitto (free, open source), HiveMQ Community Edition, EMQX Open Source, and VerneMQ. Sparkplug B does not require broker modifications because the broker never reads the Protobuf payload. HiveMQ Enterprise and EMQX Enterprise offer optional Sparkplug B extensions that add broker-side session awareness, monitoring dashboards, and Sparkplug-aware message management, but these are optional enhancements rather than requirements. For production IIoT deployments, HiveMQ and EMQX are the most commonly deployed enterprise brokers with strong Sparkplug B ecosystem support.


