Sparkplug metric aliases let an edge node replace long metric names such as Line2/Filler/Motor/CurrentAmps with a small integer in every DATA message. In this guide you will learn how the alias mapping between BIRTH and DATA messages works, when aliases are worth the extra complexity, and how to find and fix alias mismatches when decoded values suddenly look wrong.
Why Metric Names Are Expensive
Sparkplug B payloads are Protobuf, which is already compact. Numbers are varint encoded, timestamps are 64-bit integers, and there is no JSON punctuation. The one part of a payload Protobuf cannot shrink is a string, and metric names are strings.
Industrial naming conventions make those strings long. A tag path copied from a PLC or SCADA tag browser often carries the area, the machine, the subsystem and the signal: Packaging/Line2/Filler/Infeed/Motor1/Current. When a DDATA message reports one changed value, that 45-character name can be several times larger than the value and timestamp combined.
On a wired plant network this rarely matters. On cellular links, satellite links, licensed radio or busy shared networks, it matters a great deal. Every byte is paid for, either in money or in latency. Sparkplug metric aliases are the specification's answer: send the name once, then refer to it by number.
How Sparkplug Metric Aliases Work
The mechanism has three rules.
- In the NBIRTH (for node-level metrics) or DBIRTH (for device metrics), each metric is sent with both its
nameand analias, an unsigned 64-bit integer. - In subsequent NDATA, DDATA, NCMD and DCMD messages, the metric is sent with only the
alias. Thenamefield is omitted. - Aliases must be unique within the scope of an edge node. Two metrics on the same edge node, even on different devices, cannot share an alias.
A primary host application or any other consumer builds a lookup table when it receives the BIRTH. From then on, every DATA metric that arrives with an alias is resolved back to its full name through that table.
Here is the same metric in both message types, shown as the decoded Protobuf structure:
DBIRTH spBv1.0/plant1/DBIRTH/edge-07/filler-02
metric { name: "Infeed/Motor1/Current" alias: 12 datatype: Float float_value: 4.81 }
metric { name: "Infeed/Motor1/Running" alias: 13 datatype: Boolean boolean_value: true }
DDATA spBv1.0/plant1/DDATA/edge-07/filler-02
metric { alias: 12 datatype: Float float_value: 4.93 timestamp: 1792137600123 }
The DDATA metric carries no name at all. Without the DBIRTH, a consumer has a float and the number 12, and nothing else.
What Aliases Do Not Change
Aliases only replace the name. The datatype, value, timestamp, quality properties and metadata work exactly as before. Topics also stay the same: aliases have nothing to do with MQTT 5 topic aliases, which shorten the topic string at the protocol level. The two can coexist, but they are independent features defined by different specifications. If you want the MQTT-level version, see the topic alias section in our MQTT 5 features guide.
Names vs Aliases: Trade-offs
| Aspect | Names in every DATA message | Sparkplug metric aliases |
|---|---|---|
| Payload size | Grows with name length | Small and roughly constant per metric |
| Debuggability | Any captured message is self-describing | DATA is meaningless without its BIRTH |
| Late subscribers | Can decode immediately | Must wait for or request a rebirth |
| Consumer complexity | Simple | Must maintain an alias table per edge node |
| Risk of silent errors | Low | A stale table maps values to the wrong metric |
| Best fit | Wired LAN, low tag counts | Metered or constrained links, high tag counts |
The last row in the risk column is the one that matters. A wrong name is obvious. A wrong alias is not: the consumer happily writes a motor current into a temperature tag, and the number looks plausible.
The Alias Lifecycle in Practice
Aliases are only valid for the lifetime of a single BIRTH. Understanding when that lifetime ends prevents most bugs.
- NBIRTH resets everything. When an edge node publishes a new NBIRTH, every alias table for that node is discarded and rebuilt from the new NBIRTH and the DBIRTHs that follow. An edge node is free to assign different alias numbers after a rebirth, so a consumer must never cache aliases across births.
- NDEATH invalidates the table. When the broker publishes the edge node's NDEATH will message, consumers should mark the node's metrics stale and stop trusting the alias table until the next NBIRTH.
- DBIRTH can add device metrics. A device can be rebirthed on its own, and its metrics' aliases must still be unique across the whole edge node.
- Rebirth requests recover lost state. A host that sees an alias it does not know should send an NCMD with the
Node Control/Rebirthmetric set to true, rather than guessing. Our article on Sparkplug rebirth covers that flow in detail.
The sequence number helps too. Every Sparkplug message from an edge node carries a seq from 0 to 255 that wraps around. If a consumer sees a gap, it may have missed a BIRTH and should request a rebirth before trusting aliases again. The rules for BIRTH and DEATH messages are explained in Sparkplug birth and death certificates.
Decoding Aliased Data in Python
The following script subscribes to all Sparkplug traffic for one group, builds alias tables from NBIRTH and DBIRTH messages, and resolves DATA metrics back to names. It uses sparkplug_b_pb2.py, the generated Protobuf module from the Eclipse Tahu project; copy it next to the script and install the dependencies with pip install paho-mqtt protobuf.
import paho.mqtt.client as mqtt
import sparkplug_b_pb2
BROKER = "broker.connectmq.com"
GROUP = "demo-7f3k2" # use your own unique group ID on the public broker
alias_tables = {} # edge_node_id -> {alias: name}
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code)
client.subscribe(f"spBv1.0/{GROUP}/#", qos=0)
def on_message(client, userdata, msg):
parts = msg.topic.split("/")
if len(parts) < 4:
return
msg_type, edge_node = parts[2], parts[3]
device = parts[4] if len(parts) > 4 else None
payload = sparkplug_b_pb2.Payload()
payload.ParseFromString(msg.payload)
if msg_type == "NBIRTH":
alias_tables[edge_node] = {} # a new NBIRTH resets all aliases
if msg_type in ("NBIRTH", "DBIRTH"):
table = alias_tables.setdefault(edge_node, {})
for m in payload.metrics:
if m.HasField("alias"):
if m.alias in table and table[m.alias] != m.name:
print(f"WARNING duplicate alias {m.alias} on {edge_node}")
table[m.alias] = m.name
print(f"{msg_type} {edge_node}/{device or ''}: {len(alias_tables[edge_node])} aliases")
return
if msg_type == "NDEATH":
alias_tables.pop(edge_node, None)
print(f"NDEATH {edge_node}: alias table cleared")
return
if msg_type in ("NDATA", "DDATA"):
table = alias_tables.get(edge_node)
for m in payload.metrics:
name = m.name
if not name and m.HasField("alias"):
if table is None or m.alias not in table:
print(f"UNKNOWN alias {m.alias} from {edge_node}, request a rebirth")
continue
name = table[m.alias]
value = getattr(m, m.WhichOneof("value")) if m.WhichOneof("value") else None
print(f"{edge_node}/{device or ''} {name} = {value} (seq {payload.seq})")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="alias-decoder-7f3k2")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=60)
client.loop_forever()
To produce test traffic with aliases, pair this with the publisher from our Sparkplug B edge node simulator tutorial. Both scripts work against the free public MQTT broker at broker.connectmq.com. Remember that the public broker is readable by anyone, so use a random group ID and never publish real plant data there.
Debugging Alias Mismatches
Most alias problems fall into a handful of patterns. Use this checklist when decoded values look wrong.
- Consumer started after the BIRTH. BIRTH messages are not retained in Sparkplug, so a consumer that connects later sees only aliased DATA. The fix is a rebirth request, or a primary host application that triggers rebirths automatically.
- Stale cache after a rebirth. If a consumer keeps its old table after a new NBIRTH, values land on the wrong names. Reset on every NBIRTH, as the script above does.
- Duplicate aliases across devices. Some edge configurations number aliases per device starting at 1. Two devices then both claim alias 1, which violates the uniqueness rule and corrupts any consumer that keys tables by edge node.
- Alias of zero treated as missing. In Protobuf, a field set to its default value can be indistinguishable from an absent field depending on how the code checks it. Starting aliases at 1 avoids an entire class of bugs.
- Mixed names and aliases. A DATA metric may legally include both name and alias. Consumers should prefer the name when present, and edge nodes should be consistent.
- Multiple publishers using one edge node ID. Two gateways configured with the same group and edge node ID overwrite each other's births. The symptom is aliases that flip between meanings.
Visual inspection speeds this up. ConnectMQ decodes Sparkplug B payloads, Protobuf or JSON, so in the portal's live topic explorer you can open the BIRTH and the DATA messages side by side and check that alias 12 really is the metric you expect. ConnectMQ can also republish Sparkplug B data into readable ISA-95 topics, for example spBv1.0/factory1/DDATA/line1/cnc1 into connectmq/factory1/production/line1/cnc1/telemetry, which gives non-Sparkplug consumers a path that does not depend on alias tables at all.
When Should You Enable Aliases?
Aliases are optional. Enable them when the link between edge and broker is metered or constrained, when tag counts are high and names are long, or when a single gateway publishes many metrics at a fast rate. Keep plain names when you are prototyping, when many lightweight consumers subscribe directly without a primary host, or when debuggability matters more than bytes.
A middle path works well for many teams: develop and commission with names, measure payload sizes under realistic load, and switch on aliases only on the sites whose links need it. Because aliases are negotiated entirely inside the BIRTH, consumers that implement the lookup correctly do not need any configuration change when you flip the switch.
For more context on where Sparkplug fits in a plant architecture, our industrial IoT MQTT guide covers the bigger picture, and the Sparkplug B payload article explains every field you saw in the decoded output above. The authoritative definition of alias behaviour is the Eclipse Sparkplug specification.
Test Sparkplug Aliases on ConnectMQ
Running edge nodes and host applications against a broker you control is the fastest way to validate alias handling before it reaches production. ConnectMQ is a managed MQTT broker with MQTT 3.1.1 and 5.0, TLS on port 8883 and built-in Sparkplug B decoding in the portal. Create a broker on the free Serverless plan at app.connectmq.com, no credit card required, then point your edge node at it with the generated username, password and client ID.
Frequently Asked Questions
Are Sparkplug metric aliases mandatory?
No. Aliases are optional in Sparkplug B. An edge node can send full metric names in every DATA message, and consumers must handle both forms.
Can alias numbers change between births?
Yes. Aliases are only valid until the next NBIRTH from that edge node. Consumers must rebuild their tables on every NBIRTH and never persist aliases across sessions.
What should a host do with an unknown alias?
It should not guess. The correct response is to send an NCMD with Node Control/Rebirth set to true so the edge node republishes its BIRTH messages and the full alias mapping.
Are Sparkplug aliases the same as MQTT 5 topic aliases?
No. Sparkplug metric aliases replace metric names inside the payload, while MQTT 5 topic aliases replace the topic string at the protocol level. They are independent and can be used together.



