Phantom events generated during Sparkplug B DBIRTH corrupt historian-based KPI statistics

Hello everyone,

We are running a Unified Namespace using Ignition’s MQTT Transmission module with Sparkplug B, publishing into Canary. Our environment includes both high-frequency industrial process tags and very low-frequency quality-analysis results.

Whenever Ignition’s MQTT Transmitter generates a DBIRTH—typically triggered by tag creation, tag edits, module restarts, or minor network interruptions—the transmitter republishes all existing tag values with a new timestamp, even when no real process change has occurred.

From a Sparkplug B protocol perspective this is expected behavior, since a DBIRTH message is meant to provide a complete state snapshot. However, for historians and analytical systems, this creates phantom events:

  • Tens of thousands of artificial events can be generated during each DBIRTH

  • These events destroy the natural temporal spacing of low-frequency variables

  • The result is distorted KPIs, including incorrect average values and inflated standard deviations

At this point, our production team no longer trusts the statistical values produced when Sparkplug B data flows into the historian, and must fall back to the legacy system for quality KPIs.

If you have seen similar behavior—especially when combining Sparkplug B with low-frequency or laboratory-type data—please share your observations or any workarounds you found.

This issue has been reported to the involved vendors, but since it aligns with the Sparkplug B specification, there is limited progress so far. Showing that this affects multiple users may help drive improvements or new options for handling DBIRTH metrics in the future.

I’d also be interested in ideas on this. We are currently working on the Sparkplug 4 spec. I wonder if BIRTHs should include both a ‘now’ timestamp and the actual event timestamp (i.e. non-phantom). This would at least give applications the flexibility and all the information… Other ideas/thoughts welcome, of course.

@wes.johnson ,thank you for the prompt response.
Modifying Sparkplug B to address this behaviour would be the ideal long-term solution, and I appreciate that our feedback is being considered for Sparkplug 4. However, adoption of a new specification will naturally take time.

In the meantime, a practical temporary workaround could be implemented on the consumer side:
a configuration option to ignore the metric values (VTQ) contained in DBIRTH messages and use only the metadata from those packets.
That would immediately prevent phantom events from corrupting statistical calculations.

Of course, if we are the only users affected by this issue, it will be difficult to justify such changes—so I’m hoping others can confirm whether they experience the same problem.

Marco

When you say consumer - is that MQTT Engine in your case or something else?

MQTT Engine and Canary Historian

Are you using Engine as an entry point to the Ignition historian? Or do you need Canary to implement this feature? Or both?

We have ignition Gateway on the plants that, using MQTT Transmitter, forward data to the EMQX broker in AWS. Ignition Cloud on AWS Subscribes to those messages’ topic with MQTT Engine and rearanges all plants’ data in one tag company wide structure. Ignition Cloud, using MQTT Transmitter, publishes that tag company wide structure in the EMQX broker. Canary, in turn subscribes to it and historizes.
TL:DR no historization is active in Ignition (plants or cloud). All historization is done in Canary.

As far as I can see, the Sparkplug B specification does not explicitly require the device/node to assign a fresh “now” timestamp to each metric included in the DBIRTH.
It only mandates that the DBIRTH contain a complete set of metrics and their current state.

If the MQTT Transmission module used the existing timestamps instead of generating new ones, the DBIRTH would still be fully compliant while also avoiding the phantom-event issue in historians.

Is there a technical reason the Ignition transmitter cannot preserve the original timestamps in the DBIRTH payload?

The main reason for this is that for real time controls, which was the primary use case for Transmission and Engine, the current tag value at Engine must be known any time it is possible. MQTT Engine introduces ‘phantom events’ as well - specifically when connection with an Edge is lost. This results in MQTT Engine setting the tag qualities to STALE for that Edge Node with a timestamp of now (Engine system time). As a result, to bring all values to ‘current known good values’, the timestamp must be newer than the staling event timestamp.

We’ve talked about lots of options on how to deal with this. But, don’t currently have a good solution. Ultimately, I would like it if Ignition historian could support a flag of some sort for this phantom events. This should allow one to historically see two different types of history:

  • What actually happened at the Edge
  • What an operator may have seen at MQTT Engine based on communication available at the time

I think this could be really helpful for post-mortem events. But again, it isn’t something we can support today.