P-12 — MQTT + Sparkplug B

The protocol carrying OT data to the cloud.

Estimated 15 minutes.

Designed for bad networks

MQTT was invented in 1999 at IBM by Andy Stanford-Clark and Arlen Nipper, originally to monitor oil-and-gas pipelines over satellite. Bandwidth was tiny, links were intermittent, devices were small. Twenty years later, those same constraints describe the IIoT — and that is why MQTT became the default cloud protocol for industrial data.

A 2-byte header is the whole point

An MQTT PUBLISH packet has just 2 bytes of fixed overhead. HTTP needs hundreds. On a metered cellular link, that difference is the difference between viable and not. MQTT is also fully asynchronous — clients only need to make outbound connections, so they sail through corporate firewalls.

Publish and subscribe — not request/reply

MQTT replaces "ask the device for a value" with "publish values to a topic; whoever cares subscribes". Publishers and subscribers never talk directly — a broker sits in the middle and does the routing.

A PLC, an edge gateway, a broker, many consumers

Add a consumer

A plant publishes 200 tags to MQTT. A new analytics platform wants to consume them in real time. What changes on the PLC?

  • A new connection must be opened from the PLC
  • Nothing — the analytics tool just subscribes to the broker
  • The PLC must republish to a second broker

Topics — a hierarchical address

Topics are forward-slash-delimited strings: factory/line2/oven/temperature. Subscribers can use wildcards: + matches one level (factory/+/oven/temperature), # matches anything below (factory/#). The broker matches every published topic against every active subscription.

Wildcard match

A subscriber asks for plant1/+/temperature. Which of these will it receive?

  • plant1/oven/temperature
  • plant1/oven/zone1/temperature
  • plant2/oven/temperature
  • plant1/oven/temperature AND plant1/boiler/temperature

See pub/sub in action

Step through a real publish: who subscribes, who publishes, who receives.

Three quality-of-service levels

MQTT has three QoS levels — 0 (at most once), 1 (at least once), 2 (exactly once). Higher QoS = more handshake packets and more state on broker and client. Pick the lowest QoS that meets your requirement.

Compare QoS levels

Toggle each level to see the on-the-wire flow and the guarantee it gives.

Pick a QoS

A subscriber must accumulate kWh readings used for billing — duplicates would inflate the bill. Which QoS?

  • QoS 0 — fast
  • QoS 1 — usually enough
  • QoS 2 — exactly once

Retained messages — last known value

When a publisher sets the RETAIN flag on a message, the broker stores it as the topic's "last value". Any new subscriber instantly receives the retained message on subscribe — no need to wait for the next publish. Perfect for slowly-changing config or status that subscribers must always know.

Last Will and Testament — die loudly

When a client connects, it can register a Will message — a topic + payload the broker will publish on its behalf if it disconnects ungracefully. Every other subscriber instantly knows that client is offline. This is how MQTT detects node failure without polling.

Edge node disappears

An edge gateway loses power. It registered a Will of "offline" on topic Plant1/Status/EdgeA. What do other subscribers see?

  • Nothing — they keep waiting
  • The broker publishes "offline" on Plant1/Status/EdgeA after the keep-alive timeout
  • Their connections also drop

MQTT is unopinionated. That is the problem.

Pure MQTT only specifies how to move arbitrary payloads. It says nothing about what those payloads mean, how to structure topics, or how to know which devices are alive. Two vendors using MQTT can be completely incompatible. This is where Sparkplug B comes in.

Sparkplug B — MQTT for OT

Sparkplug B (an Eclipse Foundation spec, originated by Cirrus Link) is a thin convention on top of MQTT. It standardises three things: a hierarchical topic namespace, a binary payload format (Google Protobuf), and lifecycle management via birth/death certificates.

The namespace is fixed

Every Sparkplug topic looks like: spBv1.0/group_id/message_type/edge_node_id/device_id. Message types include NBIRTH, NDATA, NDEATH (node-level) and DBIRTH, DDATA, DDEATH (device-level). The structure is non-negotiable — and that is what makes Sparkplug interoperable.

Browse a Sparkplug topic tree

Real Sparkplug topics from a 2-plant deployment. Click each topic to see what its payload looks like.

Birth and death certificates

When an edge node connects, it publishes an NBIRTH listing every metric it owns and their initial values. When it disconnects (cleanly or via Will), an NDEATH is published. Subscribers always know the full state of a node — no missing tags, no stale values, no "I joined late and missed it" problem.

A late SCADA

A SCADA station starts up two hours after the edge nodes have been running. How does it know what tags exist and their current values?

  • It queries every PLC directly
  • It subscribes to spBv1.0/+/NBIRTH/# and asks each edge for a "Rebirth" — getting the full NBIRTH replayed
  • It waits until every tag changes naturally

Aliases shrink every message

NBIRTH/DBIRTH messages list every metric with its name AND a numeric alias. After the birth, NDATA/DDATA messages only carry the alias and the new value — saving bandwidth on every cyclic update. The receiver looks up the alias against the cached birth.

Final challenge

A factory has 12 PLCs, 4 SCADA stations, 1 historian, and a cloud analytics service. Today everything talks OPC UA point-to-point — adding a new consumer means new sessions on every PLC. The team wants to switch to MQTT/Sparkplug. What changes operationally?

  • PLCs talk to a broker once via an edge gateway; consumers subscribe to the broker. Add a consumer = subscribe; no PLC change.
  • Each PLC must open one MQTT connection per consumer.
  • Sparkplug requires every consumer to also act as a broker.

What you learned

  • MQTT is a tiny pub/sub protocol designed for bad networks (1999, IBM). 2-byte header, broker-mediated.
  • Topics are slash-delimited; + and # wildcards control subscription scope.
  • QoS 0/1/2 trade reliability for handshake overhead. Pick the lowest that fits.
  • Retained messages give every new subscriber the last known value instantly.
  • Last Will and Testament publishes a "node died" message on ungraceful disconnect.
  • Sparkplug B adds a fixed namespace, Protobuf payloads, and birth/death certificates on top of MQTT.
  • NBIRTH defines metrics + aliases; NDATA carries only aliases — small, structured, interoperable.

MQTT + Sparkplug complete

  • You understand pub/sub, QoS, retained messages, and LWT.
  • You can read a Sparkplug topic tree and explain birth/death certificates.
  • You can sketch an IIoT architecture from PLC up to cloud analytics.