Learn PLCs free
Programming Guides13 min read4 173 words

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.

IAE
Senior PLC Programmer
15+ years hands-on experience • 50+ automation projects completed
PLC
Programming Excellence

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.

Plain MQTT vs Sparkplug B comparison: topic structure, payload format, and state management Side-by-side comparison of Plain MQTT and Sparkplug B across five dimensions: topic structure, payload format, state management, interoperability, and broker requirements. Plain MQTT Topic Free-form, user-defined Payload Any bytes (JSON, CSV, binary) State LWT only (1 bit) Interop Custom per integration Broker Any MQTT broker Sparkplug B Topic Enforced spBv1.0/group/type/edge Payload Protobuf (defined schema) State BIRTH / DATA / DEATH lifecycle Interop Plug-and-play with UNS Broker Any MQTT 3.1.1 broker
Plain MQTT leaves topic naming, payload format, and state management to the developer — Sparkplug B enforces all three, enabling plug-and-play IIoT interoperability.

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.

MQTT publish-subscribe data flow from PLC publisher through broker to SCADA and analytics subscribers Horizontal flow diagram showing MQTT pub/sub: a PLC/Sensor publisher sends messages to an MQTT broker via a labeled topic, and the broker fans out to a SCADA/Historian subscriber and an Analytics/Cloud subscriber. MQTT Pub/Sub Data Flow Publisher PLC / Sensor Publish topic MQTT Broker Topics: any string QoS 0 / 1 / 2 Subscribed topics Subscriber A SCADA / Historian Subscriber B Analytics / Cloud
MQTT pub/sub: publishers send to the broker on any topic string; subscribers receive messages on topics they've subscribed to — broker is the decoupling hub.

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:

  1. Topic namespace — a rigid, hierarchical naming scheme so every message has a known, machine-parseable address
  2. 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
  3. 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 death
  • DBIRTH / DDEATH — Device birth and death
  • NDATA / DDATA — Node and device data updates
  • NCMD / DCMD — Commands from host to edge/device
  • STATE — 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_null flags
  • Optional metadata and properties

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.

Sparkplug B IIoT ecosystem technology stack from MQTT broker to UNS consumer applications Vertical stack diagram showing five layers of the Sparkplug B ecosystem from bottom to top: MQTT 3.1.1 Broker, Sparkplug B Spec, Edge Node Runtime, Host Application, and UNS Consumer Apps. Sparkplug B Ecosystem Stack MQTT 3.1.1 Broker Mosquitto / HiveMQ / EMQX (standard, no modification) Sparkplug B Spec (spBv1.0) Topic namespace + Protobuf schema Edge Node Runtime Eclipse Tahu / Ignition MQTT Transmission Host Application Ignition SCADA / HiveMQ Sparkplug ext. UNS Consumer Apps Historian / MES / Cloud Digital Twin
Sparkplug B stack: any standard MQTT broker at the foundation, the spBv1.0 spec for structure, edge node runtimes (Eclipse Tahu / Ignition), and host applications consuming the UNS.

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.

MQTT payload size comparison: plain JSON vs Sparkplug B Protobuf vs OPC UA binary for 5-metric message Horizontal bar chart comparing payload sizes in bytes for a 5-metric message across four formats: Plain MQTT JSON at 92 bytes, OPC UA Binary polled at 140 bytes, Sparkplug B DDATA with aliases at 28 bytes, and Sparkplug B DBIRTH with names at 70 bytes. Payload Size Comparison: 5-Metric Message Plain MQTT + JSON OPC UA Binary (polled) Sparkplug B DDATA (aliases) Sparkplug B DBIRTH (names) 92 bytes 140 bytes 28 bytes 70 bytes Alias optimization eliminates full metric names in DDATA after BIRTH
Payload size comparison for a 5-metric message: Sparkplug B DDATA with alias optimization (28 bytes) is ~60% smaller than plain JSON (92 bytes), saving significant bandwidth at scale.

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.

#mqttvs sparkplug b#mqtt#sparkplugb#iiot#protobuf#reportby exception
Share this article:

Related Articles