Naming and standards
Three fields carry the model on every resource: the name (what a person reads), the label (what kind of thing it is), and the external id (the permanent handle systems use).
Naming is not cosmetic. A model with inconsistent names is a model nobody trusts, and the cost of fixing it rises with every item added. Set the conventions before you import at volume.
What each field carries
| Field | What it is | Can it change? |
|---|---|---|
| Name | The readable label, written for a person scanning a list. In RDF terms, rdfs:label. | Yes, any time |
| Label | The class the resource belongs to, Pump, Separator. In RDF terms, rdf:type. | Rarely, and deliberately |
| External id | The stable identifier that follows the namespace in an IRI. Imports, integrations and the SDK match on it. | Never |
The console suggests an external id derived from the name, lowercase with underscores, and lets you override it. That derivation is a convenience for a typed name, not a rule about what an external id may look like: an id you supply yourself is stored exactly as you write it, so a plant tag stays a plant tag. Take the override seriously when the derived value would encode something unstable.
Rules of thumb
When the facility has a tagging standard, use it: 21-PT-1234 Separator inlet pressure.
The tag makes it findable by anyone who works with the plant; the description makes it
readable by anyone who does not.
One resource is one physical or logical thing. Not "the pump row in SAP", the pump.
If it says PT on the P&ID, it is PT here. Do not invent a new vocabulary; you will be the only person who speaks it.
They have their own fields. Discharge pressure, not Discharge pressure (bar, 1min avg).
Pump, Control Valve, Pressure Transmitter. Not pumps. DataHub normalises label
names on save, upper-cased, spaces becoming underscores, so Control Valve is stored as
CONTROL_VALVE. Write ControlValve and it stores as the unreadable CONTROLVALVE,
because run-together words are not split.
External ids are promises
An external id is a commitment that this identifier will refer to this thing, permanently. Everything that integrates with DataHub, imports, streaming ingestion, subscriptions, the SDK, other systems' cross-references, matches on it. One stable id per physical thing is also what guarantees one twin per thing, rather than four half-twins that disagree.
Two rules follow, and they are worth being strict about:
- Never change it. Changing an external id silently breaks every integration that refers to it, and the breakage shows up as missing data rather than as an error.
- Never reuse it. If equipment is decommissioned, its external id retires with it. Reusing it makes historical data refer to the wrong thing, which is worse than losing it.
That means: never encode anything that changes in an external id. No owner, no vendor, no physical location, no project phase, no cost centre. Those all belong in metadata, where they can be updated.
Make it unique across the whole facility, not just inside one source system. Two systems
that each have an asset_47 will collide the moment both are ingested.
Ask: "If this equipment is refurbished, moved to another area, and reassigned to a different owner and cost centre, is the external id still correct?" If not, it encodes something it should not.
What an external id may contain
External ids are stored exactly as you write them. The
platform accepts letters, digits and the separators . _ : + = -, between 3 and 256
characters, and rejects spaces, forward slashes and control characters. Nothing is rewritten
on the way in.
That guarantee matters more than it sounds. COM-99-PT-1034 stays COM-99-PT-1034, and an
IEC 81346 reference designation such as
=K1-M3+B02 keeps the = and + that carry its meaning. Your historian, your maintenance
system and DataHub therefore hold the same string, so matching a record in one against a
record in another is a comparison rather than a translation that every integration has to
reimplement identically, forever.
Contextualization →
Case is ignored for matching, kept for storage
Uniqueness ignores case. Creating com-99-pt-1034 when COM-99-PT-1034 already exists is
refused as a duplicate, and the message names the id it collides with. Lookups ignore case
for the same reason, so either spelling finds the same thing. What is stored, listed and
handed back to an integration is still exactly what you wrote.
Two spellings of one tag are two records of one asset, and that is the failure this prevents. If two things genuinely need separate identities, they need two different ids, not two cases of one.
Naming policies, making the convention enforceable
The charset above is a floor, not a house style. The convention itself, snake_case, verbatim plant tags, or a pattern of your own, is a naming policy: a rule an administrator records once and the platform then checks on every write. It is the first policy the platform actually enforces.
| Preset | What it allows |
|---|---|
| Qualified tag | The charset floor, plus at least three separator-delimited parts. COM-99-PT-1034 and =K1-M3+B02 pass; pump-1234 does not. The shipped default. |
| Verbatim tag | The charset floor and nothing further, for facilities mirroring a tagging standard they already maintain. |
| Snake case | Lowercase letters, digits and underscores only. Opt in where a house convention is wanted. |
| Pattern | An expression you supply, for a convention neither preset describes. |
What ships on, in full: the qualified-tag rule and the near-duplicate guard, both in warn mode. Out of the box nothing is refused: a short tag and a near duplicate are both written, and both are recorded for review.
That is deliberate. Each rule is a judgement the platform cannot make for you. P-101 is a
good tag at a site with one pump and a poor one at a site with forty. pump-a-01 beside an
existing pump_a_01 is usually one asset written two ways, and occasionally two tags a
facility genuinely maintains apart. Nothing in the write says which, so neither costs anyone
their data, and both land in Findings for a steward to settle. Turn either
one to reject when your conventions are settled enough to enforce.
Reject or warn
Each policy runs in one of two modes, and the difference is who gets interrupted:
- Reject. The write fails and nothing is created. The error names every offending id in the request rather than only the first, so a rejected import of 500 items is fixed in one pass instead of 500.
- Warn. The write succeeds and a finding is recorded against the entity for a data steward to review. Warn means allowed and in the queue, not allowed and forgotten.
Warn is how a convention gets tightened without stopping the business: turn the rule on in warn mode, work the queue down, then switch it to reject once the backlog is clear.
The near-duplicate guard
Independently of the preset, and always on, the platform refuses to let pump-a-01 land
beside an existing pump_a_01. It compares ids with case ignored and separator characters
folded together, so one naming intent written two ways is caught at creation.
This is the protection that lets a permissive preset be safe. Mixed separators for the same thing are how a model quietly acquires two records for one asset, and the symptom arrives months later as a search that comes back short, which nobody notices.
Two things to know about it:
- It spans the whole tenant, not one data set.
pump-a-01in one data set collides withpump_a_01in another, because those two cannot both be the identifier for one asset, and a search that misses records misses them across data set boundaries too. - It warns by default, so the write goes through and the collision is queued. Set it to
reject once you are confident the two forms are never both wanted: an operation that
genuinely maintains
21-PT-1234and21_PT_1234as different tags does exist, and the platform cannot tell that case from an accident.
Where a policy applies
A naming policy is set for the tenant and can be overridden on an individual data set. The most specific one wins, and it replaces rather than adds to the one above it: a data set carrying its own naming policy is governed by that policy alone, because a half-overridden naming rule is not something anyone can reason about.
A tenant-wide rule is the normal case. The override exists for the data set that lands records from a source system whose identifier scheme you do not control.
They apply to resources, data sets and time series — everything whose external id is a unique identity. Event external ids are exempt, deliberately: an event external id is not a name somebody chose, it is the source system's key for the subject the event is about, and events are meant to share one. The charset floor still applies to them, so a space or a control character is still refused. Why events are different →
If you configure a strict convention expecting it to cover your event streams, it will not.
The findings queue
Every warning is recorded against the entity that raised it, so the steward's queue is a list of what the convention let through rather than a log line somebody had to be watching at the time. It can be filtered by policy, by data set, and by open versus closed.
Closing a finding is a judgement, not a fix: the id still breaks the convention, someone has decided that is acceptable, and it stays closed unless the id itself changes.
Bulk imports produce findings in bulk, so the queue groups them by policy and by the shape of the mistake rather than listing them one by one. Ten thousand findings from one import are one decision, not ten thousand.
Labels, building the taxonomy
Labels are your taxonomy. Every resource needs at least one, and the
type label is singular: a resource carries at most one type, chosen at creation and fixed
afterwards, encoding what it fundamentally is. Other labels can be added and changed freely, which makes them useful for
cross-cutting tags, SafetyCritical, PilotScope, without disturbing the classification.
Guidelines:
- Aim for 15–25 classes in a first model. If you are past 60, you are probably modelling source systems rather than the operation.
- Shallow beats deep. Three or four levels of specialisation is plenty.
- Split when the split changes an answer.
ValveandControlValveshould be separate classes only if some question needs to distinguish them. Otherwise it is one class with a metadata field.
Relationships
Relationship names are the verbs of your model. A few conventions that keep traversal sensible:
- Names are stored upper-cased, so prefer single words (
feeds,monitors,powers) or spaced phrases (part of) over run-together ones:contributesTostores as the unreadableCONTRIBUTESTO. - Name what is actually asserted.
part of,feeds,monitors,powers, notrelatedTo, which carries no information and makes traversal useless. - Fix the direction and hold it. Decide once whether you write instrument monitors equipment or equipment monitoredBy instrument, and keep every instance consistent. Mixed direction is the most common cause of a query returning half its expected results.
- Keep the vocabulary small. Five to ten relationship types, used consistently, model almost any operation. Forty types used once each model nothing.
- Read it aloud as a sentence. "Line 3 contains Pump P-101." If the sentence is true and useful, the relationship name is right.
Standards this follows
Naming in industrial operations is already standardised. Follow whichever standard your facility uses and mirror it in DataHub, rather than inventing a parallel scheme.
| Standard | What it fixes |
|---|---|
| ISA-5.1 | Instrument tags. The first letter is the measured variable, the letters after it the function: PT is a pressure transmitter, TI a temperature indicator, FIC a flow indicating controller. |
| IEC/ISO 81346 | Reference designations, separating the aspects of an item with prefix signs: = for function, - for product, + for location. |
| ISO 15926 | The life-cycle data model for process plants. Part 8 maps it onto RDF and OWL, which turns the reference data library into an ontology you can query. |
| NORSOK Z-DP-002 | The coding system used on the Norwegian shelf, breaking an installation down into systems, subsystems and item tags. |
| CFIHOS (IOGP JIP36) | Fixes the equipment classes and attribute names handed over from project to operations. |
Two of these map onto DataHub especially directly:
- ISA-5.1 tags already encode the class. A tag beginning
PTtells you the resource is aPressureTransmitter, so the tag prefix can drive label assignment during import, rather than someone classifying 4,000 instruments by hand. - IEC/ISO 81346's aspects are exactly the three layers:
function (
=), product (-) and location (+) are three different relationships from the same item, which is precisely what a graph represents naturally and a hierarchy cannot. The aspect prefixes are also part of the accepted charset, so a designation such as=K1-M3+B02is a valid external id written exactly that way.
CFIHOS-conformant handover data is close to a ready-made layer-1 model. Landing it into DataHub at handover, rather than into a folder of spreadsheets, is one of the highest-return moments available, because the information is complete and verified exactly once in an asset's life. The handover play →
Where the help lives in the console
Every resource, time series and data set form has a naming help icon next to the fields. It opens the same conventions summarised here, including the RDF view of an example asset and the standards list, so the guidance is available at the moment somebody is naming something, which is when it actually gets read.
- Taxonomy, ontology, knowledge graph: what labels and relationships are doing
- What is an ontology?: the model layer, and the RDF alignment
- Building your model: agreeing conventions before you scale
- Working with resources: the forms these fields appear on
- Policies: where a naming policy is recorded, alongside the other rules on a data set
- Events: the one place an external id means something different