MQTT is deliberately unopinionated about what your payloads contain, how you structure your topics, or how devices announce themselves to the network. That flexibility is a big part of why MQTT is popular. It is also the reason MQTT alone is not enough for industrial IoT, where two vendors’ devices need to interoperate on the same broker, where SCADA systems need to know instantly whether a device is online or offline, and where every metric on the network needs a precise, machine-readable definition. Without agreed conventions, connecting a hundred devices from a dozen vendors is a hundred custom integrations.
Sparkplug B is the specification that fills this gap. It defines a standardized topic namespace, a strongly-typed Protocol Buffers payload format, and a device lifecycle state management model on top of MQTT, purpose-built for SCADA and industrial IoT deployments. It is maintained as an open specification by the Eclipse Foundation and has become close to mandatory in modern SCADA-to-IT integration projects that use MQTT.
This article covers what Sparkplug B actually is, why it exists, how its three main pillars (topic namespace, payload, state management) work, how a Sparkplug session flows from birth to death, how it fits into Unified Namespace architectures, and how it differs from plain MQTT and from Sparkplug A. It is a technical reference; the flagship What Is MQTT article and the Open Source MQTT Broker comparison cover the underlying protocol and broker landscape.
Table of Contents
Sparkplug B at a glance
| Property | Detail |
|---|---|
| Full name | Sparkplug (originally “Sparkplug B” for the payload encoding scheme) |
| Current version | Sparkplug 3.0 (November 2022) |
| Maintained by | Eclipse Foundation, via the Eclipse Sparkplug Working Group |
| Predecessor | Eclipse Tahu project (implementation), Sparkplug A (earlier payload scheme) |
| Underlying protocol | MQTT (3.1.1 or 5.0) |
| Payload encoding | Google Protocol Buffers |
| Topic namespace | Fixed 5-element hierarchical structure |
| State management | Birth and death certificates |
| Primary use case | Industrial IoT, SCADA, Unified Namespace |
| License | Eclipse Public License |
| Original author | Arlen Nipper (co-inventor of MQTT) via Cirrus Link |
Why Sparkplug B exists
To understand what Sparkplug B provides, it helps to see the specific problems that MQTT alone leaves to the application. Three of them matter most for industrial IoT.
Problem 1: MQTT is payload-agnostic. The broker treats every payload as an opaque byte string. That is deliberate and useful — MQTT can carry anything. But it means that two vendors’ devices publishing “temperature” to the same broker will happily use completely different payload formats. One might send 22.4, another {"value":22.4,"unit":"C"}, another a binary protobuf blob. Every consumer of that data has to know, out of band, how to decode each publisher’s format. Multiply this across dozens of vendors and thousands of metrics, and integration becomes the dominant cost of an MQTT-based industrial deployment.
Problem 2: MQTT topics have no standardized structure. The protocol says topics are /-separated UTF-8 strings and matches them with wildcards, but it does not specify what they should contain. One vendor uses factory1/line3/motor5/rpm; another uses equipment.plant1.motor5.speed; a third uses data/motor5/rpm. When new consumers arrive, they must learn every convention. When a device is replaced by a different vendor, the topic structure changes and every downstream consumer breaks.
Problem 3: MQTT does not track device state. MQTT knows whether a client is connected to the broker (via keep-alive and Last Will), but it does not know what data that client publishes or what its current values are. If a SCADA system subscribes late, it does not receive any data until the next publish cycle. If a device silently drops offline and its retained messages go stale, consumers may keep displaying values that are hours or days old. For industrial SCADA, where operators need to know instantly whether a value is current or stale, this is a serious problem.
Sparkplug B addresses all three problems with a coordinated set of conventions layered on top of standard MQTT. The result is that any Sparkplug-compliant device can talk to any Sparkplug-compliant application through any standard MQTT broker, without custom integration.
Arlen Nipper, co-inventor of MQTT and CTO of Cirrus Link, created the original Sparkplug specification to bring MQTT back to the industrial market it was originally designed for. The specification moved to the Eclipse Foundation as an open standard, and version 3.0 (released November 2022) was the first version managed under the formal Eclipse Foundation Specification Process. Sparkplug 4.0 is currently in development.
The three pillars of Sparkplug B
Sparkplug B rests on three specifications that work together: the topic namespace, the payload format, and the state management model. Any implementation must implement all three; you cannot have partial Sparkplug B.
Pillar 1: The Sparkplug B topic namespace
Every Sparkplug B message publishes to a topic that follows a fixed five-element structure:
namespace/group_id/message_type/edge_node_id/[device_id]
The elements have specific meanings:
- namespace — always
spBv1.0for Sparkplug B version 1.0. This is a version identifier that lets consumers filter Sparkplug traffic from other MQTT traffic on the same broker. Future versions will use different namespace strings. - group_id — a logical grouping of Edge Nodes, typically representing a physical location (a plant, a site, a production line) or a functional grouping.
- message_type — one of the specific Sparkplug message types:
NBIRTH,NDEATH,NDATA,DBIRTH,DDEATH,DDATA,NCMD,DCMD, orSTATE. Each has a specific role in the state management model (covered below). - edge_node_id — the identifier of the Edge Node publishing the message. An Edge Node is a Sparkplug-aware device or gateway that participates in the Sparkplug session.
- device_id — optional final element identifying a specific device attached to the Edge Node. Present for device-level messages (
DBIRTH,DDATA,DDEATH,DCMD), omitted for Edge-Node-level messages (NBIRTH,NDATA,NDEATH,NCMD).
An example: spBv1.0/Plant1/DDATA/EdgeNode3/PumpStation5 is a data message from a device called PumpStation5, attached to EdgeNode3, in the group Plant1.
The fixed namespace is what makes cross-vendor interoperability practical. A SCADA application subscribing to spBv1.0/# receives every Sparkplug B message on the broker, regardless of which vendor produced it, and knows exactly how to parse each element of the topic string. A dashboard subscribing to spBv1.0/Plant1/+/+/+ receives every message from Plant1.
Pillar 2: The Sparkplug B payload
Every Sparkplug B message payload is encoded using Google Protocol Buffers (protobuf), following a specific Sparkplug protobuf schema. This is the “B” in Sparkplug B: the payload encoding version.
Protobuf gives Sparkplug B several important properties:
- Compact. Protobuf is a binary format designed for efficiency. A Sparkplug B payload carrying a handful of numeric metrics is typically much smaller than the equivalent JSON, which matters for bandwidth-constrained industrial networks.
- Strongly typed. Every metric has a declared data type (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float, Double, Boolean, String, DateTime, and others). Consumers know exactly how to interpret the bytes, without ambiguity.
- Schema-defined. The Sparkplug protobuf schema is published as part of the specification. Any implementation can generate encoder and decoder code from it in any language protobuf supports (which is most of them).
- Extensible. New fields can be added to the schema without breaking existing consumers, as long as they follow standard protobuf compatibility rules.
Inside a Sparkplug B payload, the main content is a set of metrics, each with a name, a data type, and a value. A single message can carry many metrics. Metrics can also carry metadata like engineering units, quality flags, timestamps, and aliases.
Sparkplug B also supports metric aliases — small integer identifiers that can substitute for the full metric name after an initial birth message that establishes the mapping. This significantly reduces bandwidth on ongoing data messages, since a long name like Enterprise/Site1/Area2/Line3/Cell5/MotorSpeed can be replaced by a single integer once the birth message has established that alias 42 means that metric.
Pillar 3: State management with birth and death certificates
The state management model is what makes Sparkplug B genuinely different from plain MQTT. It uses two paired concepts, birth and death, to give every consumer a complete, current picture of every publisher on the network.
Birth certificates (NBIRTH and DBIRTH) are the initial messages a device or Edge Node sends when it connects to the broker. A birth certificate contains the complete current state of every metric the publisher will report: all names, all data types, all current values, and any metadata. From a birth certificate, a subscriber has a full picture of everything the publisher is capable of reporting and what its current values are.
Death certificates (NDEATH and DDEATH) are the messages the broker publishes when the publisher disconnects. In practice, NDEATH is registered as the MQTT Last Will and Testament message when the Edge Node connects — meaning the broker publishes it automatically the moment the Edge Node disconnects ungracefully. DDEATH is published by the Edge Node when a specific attached device goes offline.
Data messages (NDATA and DDATA) follow birth certificates and carry only the metrics that have changed, using report by exception — publish only when a value changes, not on every cycle. This is what keeps Sparkplug B efficient at scale: after the birth message, only deltas flow across the network.
Command messages (NCMD and DCMD) let a subscriber send commands back to an Edge Node or device to change metric values or trigger actions. This is the bidirectional half of Sparkplug B — a SCADA system can not only read from Sparkplug devices but also write to them, all through the same topic namespace and payload format.
A special STATE message is used by the Sparkplug Host Application (the SCADA system or similar consumer) to announce its own state to the network. When a Sparkplug host is online, it publishes a state message; when it goes offline, its Last Will publishes the corresponding offline state. This lets Edge Nodes know whether their commands have anyone listening.
The result of this coordinated birth/death/data/command flow is that at any moment, every consumer on the network can know exactly which devices are connected, exactly which metrics they report, and exactly what the current value of each metric is — even for consumers that joined after the initial connection. Sparkplug B calls this stateful behavior, in contrast to MQTT’s stateless nature.
How a Sparkplug B session flows
To make the model concrete, trace a single Edge Node through its lifecycle.
- Edge Node connects to the broker. The Edge Node opens an MQTT connection, authenticating via TLS + username/password or client certificate. In its CONNECT packet, it registers a Last Will message for its
NDEATHtopic, so if the connection drops ungracefully, the broker publishes the death certificate automatically. - Edge Node publishes NBIRTH. The Edge Node publishes its birth certificate to
spBv1.0/group_id/NBIRTH/edge_node_id. The payload contains all metrics the Edge Node itself will report, with their names, types, current values, and metadata. Every subscriber immediately receives a complete picture of the Edge Node. - Attached devices publish DBIRTH. For each device attached to the Edge Node (perhaps a PLC, a sensor cluster, a variable-frequency drive), the Edge Node publishes a device birth certificate to
spBv1.0/group_id/DBIRTH/edge_node_id/device_id. Again, this contains complete initial state for the device’s metrics. - Data flows via NDATA and DDATA (report by exception). As metric values change, the Edge Node publishes updates on
spBv1.0/group_id/NDATA/edge_node_id(for its own metrics) orspBv1.0/group_id/DDATA/edge_node_id/device_id(for attached device metrics). Only changed metrics are included in each message — unchanged metrics are not re-transmitted. The bandwidth cost of ongoing operation is proportional to the rate of change, not the number of metrics. - Commands flow via NCMD and DCMD. A Sparkplug host application (a SCADA system) can publish commands to the Edge Node or its devices. A command is a metric write: set setpoint to 75.0, or start-pump = true. The Edge Node receives the command, executes it, and typically publishes an NDATA or DDATA reflecting the new value.
- Devices disconnect (DDEATH). When a device attached to the Edge Node goes offline (a sensor fails, a PLC is powered off), the Edge Node publishes a
DDEATHfor that device. Subscribers now know that device is no longer reporting, and its metrics should be flagged as stale. - Edge Node disconnects (NDEATH). When the Edge Node itself goes offline, either gracefully (publishing NDEATH itself) or ungracefully (the broker publishes NDEATH as Last Will), every subscriber learns the Edge Node and all its attached devices are gone.
- The next Edge Node connect starts a new session. When the Edge Node reconnects, the cycle starts over with a fresh NBIRTH containing new sequence numbers and current state. Late-joining subscribers get the full picture from the birth message.
The sequence_number field on each Sparkplug message ensures subscribers can detect missed messages and request retransmission if needed. A subscriber that sees sequence numbers jumping from 47 to 49 knows message 48 was lost.
Sparkplug B and the Unified Namespace (UNS)
Unified Namespace (UNS) is an architectural pattern where all industrial data flows through a single MQTT topic tree organized to mirror the physical or logical structure of the enterprise. In practice, UNS deployments almost always use Sparkplug B as the standard payload and state model, because UNS on its own is a topic-structure convention and needs Sparkplug B to solve the interoperability, typing, and state-management problems that raw MQTT leaves open.
The relationship between the two is roughly:
- UNS provides the organizing principle: one namespace, hierarchically structured (typically along ISA-95 lines: Enterprise / Site / Area / Line / Cell / Equipment), where every piece of industrial data has a single canonical location.
- Sparkplug B provides the mechanics: the topic namespace, the payload format, and the state management that make devices from different vendors actually work together in the UNS.
Some UNS purists argue that Sparkplug B’s fixed topic structure (namespace/group_id/message_type/edge_node_id/device_id) does not exactly match the ISA-95-style UNS hierarchy, and there is a design tension between the two. In practice, most industrial deployments find they can layer Sparkplug B onto a UNS by using the group_id and edge_node_id/device_id elements to encode the UNS position, or by publishing to both a Sparkplug-native namespace and a UNS-mirrored namespace. The details are covered in more depth in dedicated UNS resources; the point here is that Sparkplug B and UNS are complementary, not competing, and modern industrial IoT deployments typically use both.
For MQTT brokers that natively support Sparkplug B (EMQX via plugin, HiveMQ Enterprise via extension), the broker itself can decode Sparkplug B payloads, route them by metric name, and expose them to other systems in the UNS. This is what makes broker-native Sparkplug B support genuinely valuable for UNS deployments.
Sparkplug B versus Sparkplug A
Sparkplug B is the encoding scheme most implementations use today, but it is worth understanding what the “B” refers to. Sparkplug A was the original version of the specification and used the protobuf schema from Eclipse Kura (an IoT edge framework) for payload encoding. This turned out to be too limited to handle the metadata typical Sparkplug payloads need (data types, engineering units, quality flags, aliases, historical metadata).
Sparkplug B was developed to replace the Kura payload with a purpose-built protobuf schema that adds:
- Full metric metadata (types, units, quality)
- Metric aliases (for bandwidth reduction)
- Historical metrics (for backfill after connection restoration)
- Extended data types
- Improved timestamping
The “B” in Sparkplug B refers specifically to this second payload encoding scheme; the state management and topic namespace are shared conceptually between A and B. In practice, essentially all current Sparkplug implementations use the B encoding. When people say “Sparkplug,” they almost always mean Sparkplug B.
Sparkplug B versus plain MQTT
Since Sparkplug B runs on top of MQTT, it is worth being explicit about what changes and what stays the same.
What is the same: The underlying transport is standard MQTT. Any compliant MQTT broker (Mosquitto, EMQX, HiveMQ, VerneMQ, or others) can carry Sparkplug B traffic without modification. TLS security, QoS levels, keep-alive, wildcards, and every other MQTT feature works normally. Sparkplug B does not require MQTT 5 specifically; it works with MQTT 3.1.1 as well.
What is different:
| Aspect | Plain MQTT | Sparkplug B |
|---|---|---|
| Payload format | Application-defined | Protobuf, following Sparkplug schema |
| Topic structure | Application-defined | Fixed 5-element namespace |
| State tracking | No | Yes (birth/death certificates) |
| Metric metadata | In payload conventions | In the protobuf schema |
| Command semantics | Application-defined | Standardized NCMD/DCMD |
| Cross-vendor interop | Requires custom integration | Native |
A team that publishes JSON payloads to arbitrary topics on Mosquitto is doing “MQTT.” A team that publishes Sparkplug-encoded protobuf payloads with birth/death certificates on the fixed namespace to the same Mosquitto is doing “Sparkplug B.” Both use the same broker; the difference is in the conventions layered on top.
Sparkplug B is not “better” than plain MQTT — it is a specialization of MQTT for industrial IoT that trades flexibility for interoperability. For non-industrial deployments (consumer IoT, chat applications, general messaging), plain MQTT remains the right choice. For industrial deployments where cross-vendor interoperability and stateful SCADA integration matter, Sparkplug B is close to mandatory.
Broker support for Sparkplug B
Sparkplug B works on any standard MQTT broker as far as transport is concerned — the broker just carries opaque payloads. The difference between brokers is whether they understand Sparkplug B natively, which lets them decode payloads, route by metric name, and expose Sparkplug data to backend integrations.
Native Sparkplug B support across the major open-source brokers:
- EMQX — supports Sparkplug B via a plugin with codec functions for decoding and encoding Sparkplug payloads. Works with the EMQX rule engine to route Sparkplug data to Kafka, databases, and other backend systems.
- HiveMQ CE — no native Sparkplug B support in the Community Edition. HiveMQ Enterprise offers native Sparkplug B support via an extension.
- Mosquitto — no native Sparkplug B support. Mosquitto can carry Sparkplug B traffic as opaque payloads, but does not decode or act on Sparkplug messages.
- VerneMQ — no native Sparkplug B support.
Commercial industrial IoT platforms and SCADA products (Ignition by Inductive Automation, Cirrus Link’s MQTT modules, HighByte Intelligence Hub, and others) provide extensive Sparkplug B support as core features, since that is the industrial market they primarily serve.
For deployments building serious Sparkplug B infrastructure from open-source components, EMQX is the most common choice today, with HiveMQ Enterprise a strong alternative when its Java-based architecture and support model are preferred. The Open Source MQTT Broker comparison article covers the broader broker landscape in detail.
When to use Sparkplug B
The decision to use Sparkplug B is really a decision about whether your deployment fits its target domain.
Use Sparkplug B if you are building any of:
- SCADA systems where the operator needs current, valid data from every device at all times.
- Industrial IoT platforms integrating devices from multiple vendors on the same broker.
- Unified Namespace (UNS) architectures for enterprise-wide industrial data.
- MES (Manufacturing Execution Systems), MOM (Manufacturing Operations Management), or similar systems that need standardized industrial data flow.
- Data historians and industrial analytics platforms consuming from OT sources.
- Any project where you would otherwise be building custom protobuf schemas, state management, and topic conventions on top of MQTT for industrial data.
Do not use Sparkplug B if your deployment is:
- Consumer IoT (home automation, connected products for end users).
- General-purpose messaging (chat, notifications, event distribution).
- Simple telemetry where cross-vendor interoperability and stateful management are not concerns.
- Very small or single-vendor deployments where the overhead of Sparkplug conventions is not justified.
The specification’s own targeting language is clear: Sparkplug’s aim is “real-time SCADA/Control HMI solutions,” and it succeeds at that because it does not try to be everything. For everything outside that domain, plain MQTT (or an MQTT variant like WebSockets) is a better fit.
The Sparkplug ecosystem
The Sparkplug specification is maintained by the Eclipse Sparkplug Working Group under the Eclipse Foundation. The working group includes strategic members from across the industrial IoT ecosystem, and the specification is developed openly via the Eclipse Foundation Specification Process. Key implementations include:
- Eclipse Tahu — the reference implementation project, providing Sparkplug clients in Java, Python, C, JavaScript, and others.
- Cirrus Link MQTT modules — Sparkplug B implementations for Ignition, AVEVA, and other SCADA products.
- Chariot MQTT Server — Cirrus Link’s Sparkplug-focused broker.
- HighByte Intelligence Hub — Sparkplug-aware industrial data hub.
- EMQX — MQTT broker with Sparkplug B plugin support.
- HiveMQ — MQTT broker with Sparkplug B extension in the enterprise edition.
Sparkplug 3.0 was released in November 2022 as the first version managed under the Eclipse Foundation Specification Process. It clarified ambiguities in the earlier v2.2 spec and formalized normative statements without changing the intent significantly. Sparkplug 4.0 is currently in development, with proposed changes being tracked in the Eclipse Sparkplug GitHub repository.
Compliance testing is available through the Sparkplug Technology Compatibility Kit (TCK), which vendors can use to verify their implementations against the specification. The Eclipse Foundation runs a compatibility program that lists certified products.
Frequently asked questions
What is Sparkplug B?
Sparkplug B is an open specification, maintained by the Eclipse Foundation, that defines a standardized MQTT topic namespace, a Protocol Buffers payload format, and a device lifecycle state management model for industrial IoT and SCADA applications. It is layered on top of MQTT and provides the interoperability and state tracking that plain MQTT does not.
What is the difference between MQTT and Sparkplug B?
MQTT is a general-purpose messaging protocol; Sparkplug B is a specification layered on top of MQTT that adds industrial-specific conventions for topics, payloads, and state management. Sparkplug B messages travel over standard MQTT brokers, but they follow specific rules that make them interoperable across vendors.
What is the current version of Sparkplug?
Sparkplug 3.0, released in November 2022, is the current version. It was the first version managed under the Eclipse Foundation Specification Process. Sparkplug 4.0 is currently in development.
What does the “B” in Sparkplug B mean?
It refers to the payload encoding scheme. Sparkplug A used Eclipse Kura’s protobuf definition; Sparkplug B introduced a purpose-built protobuf schema with richer metadata support. Essentially all current implementations use the B encoding.
Which MQTT brokers support Sparkplug B natively?
EMQX supports Sparkplug B via a plugin. HiveMQ Enterprise offers native support via an extension (HiveMQ CE does not). Mosquitto and VerneMQ do not have native Sparkplug B support but can carry Sparkplug traffic as opaque MQTT payloads.
Is Sparkplug B the same as Unified Namespace?
No, but they are commonly used together. Unified Namespace is an architectural pattern (a single hierarchical topic tree for enterprise-wide industrial data); Sparkplug B is a specification that defines the messaging mechanics (topic namespace, payload, state management). UNS deployments typically use Sparkplug B for the underlying mechanics.
