Industrial Intelligence Architecture

Data Modelling Examples for the Unified Namespace

Practical Unified Namespace payload examples that show how to build a small, reusable data model that can evolve with operational needs.

Kudzai Manditereza
Kudzai Manditereza
·

In the previous article, we looked at how to design the MQTT topic namespace of a Unified Namespace so consumers can predict where different classes of operational information will appear.

That leaves the other half of the problem:

What should the message published there actually look like?

One answer is to adopt an existing manufacturing data-modelling standard and require producers to conform to it. Standards can be useful, but I do not think that should automatically be the starting point. For many manufacturers, it introduces additional cost, complexity, and modelling effort as teams try to fit their operational reality into a predefined structure.

A standard model for something as simple as a weighing scale, for example, may define dozens of properties because it needs to accommodate many possible implementations. A particular manufacturer may only have five of those properties available, or may describe the same equipment quite differently.

My preference is to start with what actually exists in the operation and abstract it into a small set of reusable data models. A process value becomes a Metric. An asset becomes an EquipmentDefinition. A state change becomes an EquipmentState. An MES transition becomes an Event. Current operational information can be represented as Status, while calculated measures become KPIs.

The goal is not to model everything manufacturing could possibly contain. It is to create simple, consistent payloads for the operational information your systems actually produce and your consumers actually need.

The following examples show what that can look like in practice.

1. Metric: Representing a Measurement

The simplest place to start is with a measurement. A process pressure published beneath a topic such as:

.../Edge/Metrics/HomogenizationUnit/SecondStagePressure

might use a payload like this:

{
 "schemaVersion": "1.0.0",
 "name": "homogenizerSecondStagePressure",
 "equipmentId": "EQ-MUC-HG401",
 "value": 7.2,
 "timestamp": 1786281631002,
 "quality": "Good"
}

There is deliberately not much in the payload. It identifies the metric, identifies the equipment it belongs to, provides the value, records when it was observed, and tells the consumer something about its quality. What it does not contain is equally important. There is no equipment manufacturer, model, engineering range, OPC UA endpoint, description, or complete ISA-95 hierarchy attached to every reading.

For a measurement that may be published several times per second, repeatedly sending all of that slow-changing context would add volume without making the observation itself more useful. The richer engineering context still matters, but it does not necessarily belong in every high-frequency message.

2. MetricDefinition: Separating the Value from What It Means

Keeping the Metric payload small immediately raises another question. What does homogenizerSecondStagePressure measure? What unit is it in? What is its engineering range? Where did it come from? Those questions are important, but the answers change far less frequently than the process value itself.

That slower-changing information can be represented separately as a MetricDefinition. For example:

{
 "datatype": "Float",
 "name": "labelerSpeed",
 "description": "Labeler LBL601 throughput speed in bottles per minute",
 "engineering": {
   "engLow": 0.0,
   "engHigh": 600.0,
   "engUnit": "BPM"
 },
 "source": {
   "origin": "BatchPlantSimulator_OPCUA",
   "tag": "LBL_601_SPEED",
   "uri": "opc.tcp://localhost:26543/BatchPlantServer"
 },
 "classification": "ProcessVariable",
 "equipmentId": "EQ-MUC-LBL601",
 "quality": "Good",
 "timestamp": 1786281451999
}

This model can be published and retained beneath a predictable namespace such as:

.../Edge/MetricDefinitions/...

The result is a useful separation between fast-changing observations and the relatively static information needed to interpret them. Consumers interested only in live values can process compact Metric messages, while consumers that need engineering metadata can resolve the corresponding definition.

A Boolean measurement, for example, might add the following fields:

{
 "trueLabel": "Open",
 "falseLabel": "Closed",
 "datatype": "Boolean"
}

That does not require inventing a completely different payload model. It is still a MetricDefinition; it simply carries the additional information required to interpret that datatype.

3. EquipmentDefinition: Representing the Asset Once

Measurements frequently refer to equipment, which creates another modelling problem. If every metric, event, KPI, or state message carries the full description of the asset, the same information is duplicated throughout the UNS. A better approach is to give the equipment its own stable definition and let other messages refer to it by identity.

An EquipmentDefinition might look like this:

{
 "schemaVersion": "1.0.0",
 "equipment": {
   "id": "EQ-MUC-PMPKG1",
   "assetTag": "PM-PKG1",
   "name": "Power Monitoring Unit PM-PKG1",
   "serialNumber": "SIE-PAC4200-22-0102",
   "lifecycleStatus": "commissioned",
   "installationDate": "2022-03-22"
 },
 "equipmentDefinition": {
   "id": "EQDEF-SIE-PAC4200",
   "manufacturer": "Siemens",
   "model": "SENTRON PAC4200",
   "description": "Panel-mounted multifunction power monitoring device..."
 },
 "equipmentClass": {
   "id": "EQCLASS-POWERMONITOR",
   "name": "Power Monitoring Unit"
 },
 "parent": {
   "workCenterId": "WC-MUC-300-L1"
 },
 "source": {
   "origin": "BatchPlantSimulator_OPCUA",
   "gateway": "Ignition-Gateway-001",
   "originSystemId": 1011
 },
 "quality": "Good",
 "timestamp": 1786281450259
}

This model can be published and retained beneath a namespace such as:

...Line1/Equipment/EquipmentDefinition/PowerMonitoringUnit...

...Line1/Equipment/EquipmentDefinition/Filler...

Several useful concerns are separated inside this model. The equipment section describes the actual physical instance. equipmentDefinition describes its make and model. equipmentClass says what type of equipment it is. parent establishes where it belongs operationally, while source preserves provenance.

Most importantly, the asset now has a stable identity:

EQ-MUC-PMPKG1

That identifier can be reused across independently published messages. A Metric can carry equipmentId = EQ-MUC-PMPKG1. An EquipmentState can use the same identifier, and a KPI or production event can refer to it when the asset forms part of the operational context.

Stable identifiers allow independently published facts to be composed around a shared identity.

4. EquipmentState: Representing a Change in Condition

An equipment definition tells us what an asset is. Its operating state tells us what condition it is currently in, but it is often more useful to model the transition into that state rather than repeatedly publishing only the current label.

For example:

{
 "eventId": "8ab236c2-7f63-44c2-bd5f-65e93fe299ae",
 "schemaVersion": "1.0.0",
 "eventTime": 1786281665938,
 "stateCode": 3,
 "state": "Starved",
 "equipmentId": "EQ-MUC-FL501",
 "source": {
   "gateway": "Ignition-Gateway-001"
 },
 "quality": "Good",
 "timestamp": 1786281666028
}

This message does more than say that the asset is Starved. It records that a particular asset entered that state at a particular time. Once state changes are represented this way, downstream systems can reconstruct the sequence of operating conditions.

From those transitions, consumers can derive dwell time, transition frequency, time spent starved, duration of blocked conditions, and other useful operational measures without having to place all of those derived values into the transition message itself.

The source payload may also expose metadata such as the full enumeration of possible state codes. That information can be useful during integration, but it does not necessarily belong in every canonical state message. If valid equipment states are already governed elsewhere, the shared model only needs to communicate the operational fact that actually occurred.

5. Event: Giving Operational Changes a Common Shape

Manufacturing generates a large number of operational events. A work order is released, a batch starts, material is consumed, an inspection fails, or a maintenance activity completes. The information specific to those events can vary considerably, but the basic mechanics of representing an event are remarkably similar.

A Production event such as BatchPhaseCompleted can use a common envelope:

{
  "eventType": "BatchPhaseCompleted",
  "eventId": "EVT-PHASE-DONE-26154-0022",
  "eventVersion": "2.0",
  "timestamp": "2026-06-03T06:50:00+02:00",
  "source": {
    "origin": "BatchPlantSimulator_OPCUA",
    "uri": "opc.tcp://localhost:26543/BatchPlantServer",
    "gateway": "Ignition-Gateway-MUC-Line1",
    "originSystemId": 1015
  },
  "correlationId": "batch-BR-MUC-LINE1-260603-0419",
  "data": {
    "batchRecordId": "BR-MUC-LINE1-260603-0419",
    "producedBatch": "B-20260603-001",
    "workOrderId": "WO-MUC-26154-0007",
    "controlRecipeNumber": "CR-1000234567-01",
    "processOrderNumber": "1000234567",
    "operationNumber": "0020",
    "operationName": "Cook",
    "phaseNumber": "0022",
    "phaseName": "HeatToTarget",
    "unitName": "KT-301",
    "isa95Context": {
      "enterprise": "GlobalIndustries",
      "site": "Munich",
      "area": "ProductionArea",
      "processCell": "Line1"
    },
    "startTime": "2026-06-03T06:42:00+02:00",
    "endTime": "2026-06-03T06:50:00+02:00",
    "durationSec": 480,
    "expectedDurationSec": 480,
    "durationDeviationPct": 0,
    "status": "Complete",
    "completionReason": "SetpointReached",
    "reportParameters": {
      "actualTemperature": 90.1,
      "rampRate": 2.4,
      "steamConsumedKg": 24.6
    },
    "exitSnapshot": {
      "kettleTempC": 90.1,
      "kettleVolumeL": 1850,
      "agitationRpm": 50,
      "jacketPressureBar": 3.2
    },
    "deviations": [],
    "alarmsFired": [],
    "operatorInterventions": [],
    "phaseSignature": {
      "signedBy": "system",
      "signedAt": "2026-06-03T06:50:00+02:00",
      "reason": "Auto-sign on SetpointReached"
    }
  }
}

The top-level fields remain predictable across event types. Consumers can rely on eventType, eventId, eventVersion, timestamp, source, and correlationId, while the data object carries the information specific to the event.

A BatchStarted, WorkOrderCompleted, MaterialConsumed, or InspectionCompleted event can use the same basic envelope even though the contents of data will differ. The pattern can extend across domains as well. A Maintenance event may contain very different operational details from a Production event, but the representation of an event does not need to be reinvented.

This is where abstraction becomes especially valuable. Standardize the parts of an event that are common and predictable, while allowing the domain-specific information to remain specific.

6. Status: Representing What Is True Now

Events tell consumers what happened, but not every operational question is about change. Many applications simply need a convenient current value.

That is where Status becomes useful. The current defect rate, for example, might be represented as:

{
  "schemaVersion": "1.0.0",
  "workcentreId": "WC-MUC-300-L1",
  "name": "defectRate",
  "source": {
    "origin": "BatchPlantSimulator_OPCUA",
    "gateway": "Ignition-Gateway-001"
  },
  "units": "ppm",
  "window": "shift",
  "value": 2192,
  "timestamp": 1786281666030,
  "quality": "Good"
}

This payload is giving a consumer a useful current fact: the line is currently running at a defect rate of 2192 parts per million within the current shift context.

7. KPI: Giving Calculated Values Enough Context

KPIs represent another category of information again because the value is derived rather than directly observed.

Consider a Production KPI such as:

{
 "schemaVersion": "1.0.0",
 "name": "Performance",
 "value": 68.5,
 "unit": "%",
 "timestamp": 1786281853323,
 "quality": "Good",
 "window": "24h",
 "context": {
   "equipmentId": "EQ-MUC-FL501",
   "processCell": "Line1",
   "idealRateBpm": 200
 }
}

The value Performance = 68.5% is not very useful on its own. A consumer also needs to know what the calculation applies to, the period over which it was calculated, and sometimes the assumptions or parameters used in that calculation.

That is why a KPI model should make calculation context explicit. Fields such as window, equipment or process context, timestamp, quality, and relevant calculation parameters help turn a bare number into a reusable operational fact.

The same basic model can then be applied across Production, Quality, Energy, Maintenance, or other domains rather than allowing each function to invent a completely different way of expressing calculated performance. The meaning of the KPI will change by domain, but the basic contract for consuming it can remain familiar.

8. ControlRecipe: Modelling Operational Entities

These are operational entities: objects that exist because the business is planning, coordinating, or executing work.

A ControlRecipe is a good example. It brings together the information required to execute a particular production run, including the process order it originates from, the recipe being used, the product and batch being produced, and the equipment assigned to perform the work.

{
 "controlRecipeNumber": "CR-1000234610-01",
 "status": "CREATED",
 "destination": "BATCH_MGR_WC-MUC-200-L1",
 "source": {
   "processOrderNumber": "1000234610",
   "masterRecipe": {
     "id": "MR-KETCHUP-BULK-STD",
     "version": "01"
   }
 },
 "product": {
   "materialNumber": "SF-KETCHUP-BULK-STD",
   "producedBatch": "B-20260810-001",
   "targetQuantity": 2000,
   "unitOfMeasure": "KG"
 },
 "equipmentBinding": {
   "Cook": "KT-301",
   "PreMix": "MX-201",
   "BufferTransfer": "BT-452",
   "DeaerateAndHomogenize": [
     "DA-401",
     "HG-401"
   ]
 }
}

The same pattern applies elsewhere in the UNS. Production may contain ProcessOrder, WorkOrder, Batch, or ProductionSchedule models. Maintenance may have MaintenanceWorkOrder, while Quality may introduce Inspection or Specification. These objects come and go as work moves through the operation, but while they exist they provide essential context for understanding what the plant is doing and why.

Building a Small, Reusable Core

The models shown here are not intended to be exhaustive, nor am I suggesting that every manufacturer should adopt these exact payload structures.

The more important takeaway is the approach: start with a small, reusable core of abstractions that covers the operational information you encounter most often, and extend that core only when new requirements justify it.

Your Metric, EquipmentDefinition, Event, or KPI payloads may look different from the examples in this article. They may also look different from those used by another manufacturer. That is not necessarily a problem.

There is a strong argument for standardized industrial data models, particularly when information needs to move consistently between equipment vendors, manufacturers, suppliers, and other organizations across the wider manufacturing ecosystem.

For manufacturers building their own operational data foundations, I think the more immediate challenge is often different. They need to solve real production problems, connect existing systems, and make operational information reusable without introducing so much modelling overhead that every new use case becomes a lengthy data-standardization exercise.

In my experience, the priority for many manufacturers today is not to create the perfect universal information model. It is to create enough consistency to solve problems faster, adapt as requirements change, and support new data, analytics, and AI use cases without repeatedly rebuilding the foundation underneath them.

Index

Get the Next Guide

New architecture guides, implementation tutorials and use-case blueprints, delivered as they’re published.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

More guides

All guides →
Using TimescaleDB as an Operational Datastore for the Unified Namespace
A practical guide to using TimescaleDB as an operational datastore for the Unified Namespace, preserving metrics, events, states, and operational context for analytics and AI.
Kudzai Manditereza
Kudzai Manditereza
Using TimescaleDB as an Operational Datastore for the Unified Namespace
How to Model Events for a Unified Namespace
A practical guide to modelling operational events in a Unified Namespace for workflows, traceability, analytics, and AI.
Kudzai Manditereza
Kudzai Manditereza
How to Model Events for a Unified Namespace
Data Modelling Examples for the Unified Namespace
Practical Unified Namespace payload examples that show how to build a small, reusable data model that can evolve with operational needs.
Kudzai Manditereza
Kudzai Manditereza
Data Modelling Examples for the Unified Namespace