YAML UNS Framework Standard GitOps ISA-95 ~20 min read

YAML Definitions — Describing Your Factory as Code

An in-depth look at the UNS Framework standard YAML definitions — how factories are described today inside monolithic vendor tools, why that breaks at scale, and how a set of simple YAML files gives you a version-controlled, human-readable, machine-readable single source of truth for your entire manufacturing namespace. Includes a hands-on walkthrough of describing a small CNC shop from scratch.

How Factories Are Described Today

Every factory has a model of itself — a description of what machines exist, where they are, what they produce, and how data flows between systems. The problem is that this model almost never exists in one place. Instead, it's scattered across half a dozen systems, each with its own partial, incompatible view of reality.

Where Factory Definitions Live Today

SystemWhat It KnowsFormatWho Can Access It
SCADA / HMI Tag names, alarm thresholds, screen layouts, PLC addresses Proprietary binary project files (WinCC, FactoryTalk, Ignition) The controls engineer who built it
MES Work centres, routings, production orders, equipment IDs Relational database tables (vendor-specific schema) The MES administrator
ERP Cost centres, asset numbers, depreciation schedules SAP/Oracle tables, often with custom fields Finance and IT
CMMS Equipment hierarchy, maintenance schedules, spare parts Another vendor database (Maximo, SAP PM, Fiix) Maintenance team
Spreadsheets Machine lists, IP addresses, sensor mappings, "the master list" Excel files on a shared drive, emailed between teams Whoever last saved it
Tribal knowledge "CNC-03 is actually in Bay 4 now, not Bay 2 like the system says" Someone's head That one person who's been here 15 years

The result is that no single system has a complete, accurate, up-to-date description of the factory. The SCADA knows the tag names but not the production context. The MES knows the work centres but not the sensor addresses. The spreadsheet was accurate six months ago. And the person who knows where CNC-03 actually is — they're on holiday.

🔧

Manufacturing Engineer

You've spent hours reconciling machine lists between the MES and the SCADA. The MES calls it "MC-2001." The SCADA calls it "CNC_Bay3_Mill." The ERP calls it "Asset 40071." They're all the same machine. Nobody documented the mapping — you just know.

💻

Developer

You're building a dashboard and need to know what machines exist, what data they produce, and what topics to subscribe to. The answer is "ask Dave" or "check the spreadsheet on the S: drive." There's no API, no schema, no documentation you can programmatically consume.

🖥️

IT Engineer

You need to replicate the MQTT topic structure at a new site. The original was configured manually in the broker and the SCADA over three months. Nobody wrote down the naming conventions. You're reverse-engineering the topic tree from a packet capture.

The Monolith Problem at Scale

Each of those systems — SCADA, MES, ERP, CMMS — is a monolith. It owns its model of the factory, stores it in a proprietary format, and exposes it only through its own interface. This creates five fundamental problems that get worse as you scale.

The Five Problems

ProblemWhat HappensWhy It Gets Worse at Scale
No single source of truth Every system has a different, partial model. When they disagree — and they always disagree — there's no authoritative answer. At 1 site with 10 machines, you can keep it in your head. At 5 sites with 500 machines, the inconsistencies multiply exponentially. Nobody knows which system is "right."
No version control Someone changes a tag name in the SCADA, renames a work centre in the MES, or updates the spreadsheet. There's no record of what changed, when, or why. Configuration drift becomes invisible. Six months later, the dashboard shows wrong data and nobody can trace when it broke. Regulated industries (aerospace, pharma) can't prove compliance.
No portability The factory model is locked inside vendor-specific formats. You can't export your SCADA configuration and import it into a different tool. You can't diff two versions of your MES setup. Migrating to a new SCADA vendor means rebuilding the entire configuration from scratch. Multi-vendor environments (common at scale) mean maintaining parallel models in incompatible formats.
No automation Adding a new machine means manually updating the SCADA, the MES, the CMMS, the spreadsheet, and the MQTT broker. Each update is a separate, manual, error-prone process. At scale, "add a machine" becomes a multi-week project involving 4 teams and 6 systems. The overhead of maintaining the model exceeds the value of the model itself.
No reproducibility You can't take the factory definition from Site A and deploy it at Site B. Each site is configured independently, manually, from scratch. Multi-site rollouts take months instead of minutes. Each site drifts independently. "Standard" configurations are aspirational, not enforced.
A 2023 study by LNS Research found that manufacturers spend an average of 30% of their digital transformation budget on data integration and system reconciliation — not on building new capabilities, but on making existing systems agree on basic facts like "what machines do we have?" and "what data do they produce?" This is the tax you pay for having your factory model trapped inside monolithic vendor tools.
Source: LNS Research (2023) "The Cost of Data Integration in Manufacturing"; McKinsey (2022) "Unlocking the industrial IoT"
THE MONOLITH PROBLEM — EVERY SYSTEM HAS ITS OWN MODEL Your Factory The actual physical reality SCADA proprietary binary MES vendor database ERP SAP / Oracle CMMS Maximo / SAP PM Spreadsheet "the master list" Every system disagrees. No single source of truth. No version control.

Why GitOps for Factory Definitions

The software industry solved this exact problem 15 years ago. It was called "works on my machine" — every developer had a different environment, configured manually, impossible to reproduce. The solution was infrastructure as code: describe your infrastructure in version-controlled text files, and let tooling make reality match the description.

Software WorldManufacturing WorldThe Pattern
Dockerfile uns.yml + site.yml Describe what you have in a text file. The file is the specification.
docker-compose.yml function.yml + mqtt.yml + database.yml Describe how components connect. Services, endpoints, ports.
Kubernetes manifests UNS Framework YAML definitions Declarative: describe the desired state, not the steps to get there.
Terraform Multi-site YAML configs Same definition, different environments. Reproducible deployments.
git diff git diff site.yml See exactly what changed, when, and who changed it.
git revert git revert Undo any change instantly. Roll back to any previous state.

The UNS Framework applies this same pattern to manufacturing. Instead of your factory model being trapped inside vendor databases, spreadsheets, and tribal knowledge, it lives in YAML files in a git repository. These files are:

The GitOps pattern has been validated at massive scale in software infrastructure. A 2024 CNCF survey found that 76% of organisations using Kubernetes manage their infrastructure through GitOps workflows. The key insight that transfers to manufacturing: the git repository becomes the single source of truth, and every other system derives its state from that truth — not the other way around.
Source: CNCF (2024) "Annual Survey: GitOps Adoption"; Weaveworks (2023) "The State of GitOps"

Without GitOps

"We added CNC-05 last Tuesday. I updated the SCADA and the spreadsheet. I think someone updated the MES. The CMMS still shows the old layout. The MQTT topics were configured manually — I'm not sure if the naming matches the convention we used for the other machines."

With YAML + GitOps

git log --oneline site.ymla3f2c1d Add CNC-05 to Area 1, Cell 2. One file changed. One commit. The MQTT topics, the naming convention, the sensor model — all defined in the same YAML, all version-controlled, all consistent.

Why YAML

The UNS Framework uses YAML as its definition language. This isn't an arbitrary choice — YAML has specific properties that make it the right format for describing manufacturing infrastructure.

YAML vs Alternatives

FormatHuman-ReadableMachine-ReadableSupports HierarchyTemplates / ReuseIndustry Adoption
YAML ✓ Excellent — indentation-based, minimal syntax ✓ Parsers in every language ✓ Native nesting ✓ Anchors & aliases (& / *) Docker Compose, Kubernetes, GitHub Actions, Ansible, CloudFormation
JSON Moderate — brackets and quotes add noise ✓ Universal ✓ Native nesting ✗ No native reuse mechanism APIs, config files, data exchange
XML Poor — verbose, tag-heavy ✓ Mature parsers ✓ Native nesting Partial (XInclude, entities) Legacy enterprise, OPC UA, B2MML
TOML Good for flat config ✓ Growing support Limited — deep nesting is awkward ✗ No native reuse Rust ecosystem, some config files
Proprietary binary ✗ Requires vendor tool ✗ Vendor-locked Varies Varies SCADA, PLC, MES vendor tools

YAML wins on the combination that matters most for factory definitions: a manufacturing engineer can read and edit it without special tools, while any software system can parse and act on it programmatically. It's the same reason Docker chose YAML for Compose files and Kubernetes chose it for manifests — the format disappears, and you focus on what you're describing.

Key YAML Features for Factory Definitions

# 1. Hierarchy maps naturally to ISA-95
site:
  - name: Detroit
    area:
      - name: Machining
        line:
          - name: CNC Line 1
            cell:
              - name: Cell A

# 2. Anchors eliminate repetition
template_cnc: &cnc_sensor
  information_model:
    status: { data_type: string }
    spindle_speed: { data_type: float }

# 3. Aliases reuse templates — DRY principle
sensors:
  - id: S1
    <<: *cnc_sensor    # Inherits the full template
  - id: S2
    <<: *cnc_sensor    # Same template, different sensor

# 4. Comments document intent — crucial for team collaboration
# Added 2026-03-15 — new mill installed in Cell A
# Approved by: J. Smith (maintenance) + M. Chen (controls)
YAML is not a new technology to learn. If your team uses Docker Compose, Kubernetes, GitHub Actions, or Ansible — they already know YAML. The UNS Framework leverages this existing knowledge rather than introducing a proprietary format.

The UNS Framework Standard Definitions

The UNS Framework defines a set of standard YAML definition types that together describe your entire manufacturing namespace. Each definition type maps to a specific concept in the ISA-95 hierarchy or the supporting infrastructure. Think of them as building blocks — you compose them to describe your specific factory.

The Definition Types

DefinitionFileWhat It DescribesISA-95 Level
UNS uns.yml The namespace itself — name, region, timezone, topic structure, topic standard, information model Enterprise
Site site.yml A physical or logical location — factory, plant, building Level 4 — Site
Area site.yml A subdivision within a site — building, floor, department, bay Level 3 — Area
Line site.yml A production line within an area Level 3 — Line
Cell site.yml A workstation or unit within a line Level 2 — Cell
Equipment site.yml A machine, device, or hardware that performs tasks Level 1 — Equipment
Sensor site.yml A data source attached to equipment — temperature, pressure, status, position Level 0 — Sensor
Function function.yml A self-contained block of code that processes data in the namespace Processing
Producer producer.yml An entity that sends data into the namespace — PLC gateway, Node-RED flow, OPC UA client Data source
Consumer consumer.yml An entity that receives data from the namespace — ERP, MES, dashboard, analytics Data sink
MQTT mqtt.yml The MQTT broker — host, port, credentials Infrastructure
Database database.yml The database for historical storage — host, port, credentials Infrastructure
Artifact artifact.yml Static data and reusable templates — equipment specs, sensor catalogues Reference data

How They Map to ISA-95

The physical hierarchy definitions (Site → Area → Line → Cell → Equipment → Sensor) map directly to the ISA-95 equipment hierarchy standard. This isn't accidental — ISA-95 is the most widely adopted standard for describing manufacturing operations, and the UNS Framework's YAML structure mirrors it exactly.

YAML DEFINITIONS → ISA-95 HIERARCHY → MQTT TOPICS YAML Definition ISA-95 Level MQTT Topic Segment uns.yml → version Enterprise v1.0/ site: name / id Level 4 — Site v1.0/detroit/ area: name / id Level 3 — Area v1.0/detroit/machining/ line → cell Level 3/2 — Line / Cell .../line1/cell-a/ equipment: id / name Level 1 — Equipment .../cell-a/cnc-01/ sensor: id + info model Level 0 — Sensor .../cnc-01/s1/status Each YAML definition maps to an ISA-95 level and generates an MQTT topic segment
The UNS Framework is not a software product — it's a descriptive standard. It doesn't replace your SCADA, MES, or MQTT broker. It describes what you have in a portable, version-controlled format that any system can consume. Think of it as a Dockerfile for your factory.

Walkthrough: Describing a Small CNC Shop

Let's build a complete set of UNS Framework YAML definitions from scratch. We'll describe a small CNC machining shop with 2 machines in 1 area — enough to see every definition type in action, small enough to understand completely.

The Physical Reality

Our shop has:

Step 1: uns.yml — Define the Namespace

Start with the namespace itself. This file describes the top-level configuration — what version of the standard you're using, the topic structure, and the information model.

# uns.yml — the namespace definition
# This is the root of your factory-as-code description.

version: '1.0'

uns:
  name: 'Detroit CNC Shop'
  region: 'US'
  timezone: 'America/Detroit'
  topic_structure: 'version/site/area/line/cell/equipment/sensor/information_model/'
  topic_standard: 'ISA95'
  information_model: 'User Defined'

This tells anyone — human or machine — that this namespace follows ISA-95, uses a versioned topic structure, and is located in the US Eastern timezone. The topic_structure field is the blueprint for how every MQTT topic in the namespace will be constructed.

Step 2: site.yml — Describe the Physical Hierarchy

This is the most important file — it describes the physical structure of your factory, from site down to individual sensors. The hierarchy is nested, just like the physical reality.

# site.yml — the physical hierarchy
# Site → Area → Line → Cell → Equipment → Sensors

version: '1.0'

# ── Templates (defined once, reused everywhere) ──────────────

template_equipment: &template_equipment
  dataops:
    normalization:
      units: 'mm'
    transformation:
      timezone: 'utc'

template_sensor_cnc: &template_sensor_cnc
  information_model:
    status:
      data_type: string       # ACTIVE, IDLE, ALARM, SETUP, OFFLINE
    spindle_speed:
      data_type: float        # RPM
    feed_rate:
      data_type: float        # mm/min
    program:
      data_type: string       # Current program name
    tool:
      data_type: string       # Current tool ID
    spindle_load:
      data_type: float        # Percentage

template_sensor_env: &template_sensor_env
  information_model:
    temperature:
      data_type: float        # Celsius
    humidity:
      data_type: float        # Percentage

# ── Physical Hierarchy ────────────────────────────────────────

site:
  - name: Detroit
    id: detroit
    location: 'Detroit, MI, USA'
    area:
      - name: Machining
        id: machining
        line:
          - name: CNC Line 1
            id: line1
            cell:
              - name: Cell A
                id: cell-a
                equipment:
                  - id: 'cnc-01'
                    name: 'Haas VF-2 Mill'
                    <<: *template_equipment
                    sensors:
                      - id: 's1'
                        <<: *template_sensor_cnc

                  - id: 'cnc-02'
                    name: 'DMG Mori NLX 2500'
                    <<: *template_equipment
                    sensors:
                      - id: 's2'
                        <<: *template_sensor_cnc

                  - id: 'env-01'
                    name: 'Environment Sensor'
                    sensors:
                      - id: 's3'
                        <<: *template_sensor_env
The <<: *template_name syntax is a YAML merge key. It pulls in all the fields from the referenced anchor (&template_name). This means you define your sensor information model once and reuse it across every machine — the DRY (Don't Repeat Yourself) principle applied to factory definitions. We'll cover templates in detail in the next section.

Step 3: mqtt.yml — Describe the Broker

# mqtt.yml — MQTT broker configuration

version: '1.0'

mqtt:
  broker:
    host: 'mqtt://mqtt.detroit-factory.local'
    port: 1883
    username: 'uns-service'
    password: '${MQTT_PASSWORD}'  # Use env var for secrets

Step 4: database.yml — Describe the Historian

# database.yml — historical storage configuration

version: '1.0'

database:
  timeseries:
    host: 'postgres.detroit-factory.local'
    port: 5432
    username: 'uns'
    password: '${DATABASE_PASSWORD}'

Step 5: function.yml — Describe the Processing Functions

# function.yml — data processing functions

version: '1.0'

function:
  - name: uns-state
    endpoint: http://uns-state:8080
    # Tracks machine state transitions (ACTIVE → IDLE → ALARM)

  - name: uns-historian
    endpoint: http://uns-historian:8080
    # Logs every value change to PostgreSQL

  - name: uns-kpi
    endpoint: http://uns-kpi:8080
    # Calculates OEE, availability, performance

Step 6: producer.yml & consumer.yml — Describe Data Flow

# producer.yml — entities that send data into the namespace

version: '1.0'

producer:
  - name: Node-RED-PLC-Gateway
    endpoint: http://nodered.detroit-factory.local:1880
    # Reads Modbus from both CNCs, publishes to MQTT
# consumer.yml — entities that receive data from the namespace

version: '1.0'

consumer:
  - name: ERP-Production-Sync
    endpoint: opcua://erp.detroit-factory.local:4840
    # Pulls production counts and cycle times into ERP

The Complete File Structure

# Your factory, described as code

detroit-uns/
├── uns.yml          # Namespace: version, region, topic structure
├── site.yml         # Physical: site → area → line → cell → equipment → sensors
├── mqtt.yml         # Infrastructure: MQTT broker connection
├── database.yml     # Infrastructure: PostgreSQL connection
├── function.yml     # Processing: functions that act on the data
├── producer.yml     # Data flow: what sends data in
├── consumer.yml     # Data flow: what reads data out
└── README.md        # Documentation for the team

# Total: 7 YAML files. Your entire factory in a git repository.
# Any engineer can read it. Any tool can parse it.
# Every change is tracked. Every version is recoverable.
That's it. Seven YAML files describe your entire manufacturing namespace — the physical hierarchy, the data infrastructure, the processing functions, and the data flow. This is your single source of truth. Everything else — MQTT topics, dashboard configurations, function subscriptions — derives from these files.

Templates & Reuse with YAML Anchors

In a real factory, you don't have one machine — you have dozens or hundreds, many of the same type. Without templates, you'd copy-paste the same sensor definition for every machine. YAML anchors and aliases solve this elegantly.

How Anchors Work

# Step 1: Define the template with an anchor (&)
template_sensor_cnc: &template_sensor_cnc
  information_model:
    status:
      data_type: string
    spindle_speed:
      data_type: float
    feed_rate:
      data_type: float
    program:
      data_type: string
    tool:
      data_type: string
    spindle_load:
      data_type: float

# Step 2: Reuse with an alias (*) and merge key (<<:)
equipment:
  - id: 'cnc-01'
    sensors:
      - id: 's1'
        <<: *template_sensor_cnc   # ← All 6 fields inherited

  - id: 'cnc-02'
    sensors:
      - id: 's2'
        <<: *template_sensor_cnc   # ← Same 6 fields, no copy-paste

  - id: 'cnc-03'
    sensors:
      - id: 's3'
        <<: *template_sensor_cnc   # ← And again. Define once, use everywhere.

Why Templates Matter at Scale

ScenarioWithout TemplatesWith Templates
10 identical CNC machines Copy-paste the sensor definition 10 times. 60+ lines of duplicated YAML. Define the template once (6 lines). Reference it 10 times (1 line each). 16 lines total.
Change the information model Find and update all 10 copies. Miss one? That machine's data is now inconsistent. Update the template once. All 10 machines inherit the change automatically.
Add a new sensor field Add it to all 10 copies manually. Hope you don't introduce a typo in copy #7. Add it to the template. Done. Every machine that references the template gets the new field.
New site with same machine types Copy the entire site.yml. The templates are embedded in the copy — changes don't propagate. The new site references the same templates. Consistency is guaranteed by the YAML structure.

Templates can also be composed. An equipment template defines dataops (normalisation, transformation), while a sensor template defines the information model. Combine them for a complete machine definition:

# Equipment template — how to process the data
template_equipment: &template_equipment
  dataops:
    normalization:
      units: 'mm'
      scale: 1.0
    transformation:
      timezone: 'utc'
      aggregation:
        method: 'average'
        window: 60

# Sensor template — what data the sensor produces
template_sensor_cnc: &template_sensor_cnc
  information_model:
    status: { data_type: string }
    spindle_speed: { data_type: float }

# Compose both templates on a single machine
equipment:
  - id: 'cnc-01'
    name: 'Haas VF-2 Mill'
    <<: *template_equipment       # ← Inherits dataops
    sensors:
      - id: 's1'
        <<: *template_sensor_cnc   # ← Inherits information model

Generated MQTT Topics

The YAML definitions don't just document your factory — they define the MQTT topic tree. Each level of the hierarchy becomes a segment in the topic path, following the topic_structure defined in uns.yml.

From our walkthrough example, the following MQTT topics are generated:

CNC-01 (Haas VF-2 Mill)

v1.0/detroit/machining/line1/cell-a/cnc-01/s1/status
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/spindle_speed
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/feed_rate
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/program
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/tool
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/spindle_load

CNC-02 (DMG Mori NLX 2500)

v1.0/detroit/machining/line1/cell-a/cnc-02/s2/status
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/spindle_speed
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/feed_rate
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/program
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/tool
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/spindle_load

Environment Sensor

v1.0/detroit/machining/line1/cell-a/env-01/s3/temperature
v1.0/detroit/machining/line1/cell-a/env-01/s3/humidity

Functions

v1.0/fn/uns-state
v1.0/fn/uns-historian
v1.0/fn/uns-kpi

Every topic is deterministic — given the YAML definitions, you can compute the exact topic tree. No manual configuration, no guessing, no "ask Dave." The YAML is the specification, and the topics are the implementation.

YAML DEFINITIONS → MQTT TOPIC TREE v1.0 detroit machining line1 cell-a cnc-01 / s1 status · spindle · feed · program · tool · load cnc-02 / s2 status · spindle · feed · program · tool · load env-01 / s3 temperature · humidity 14 MQTT topics generated deterministically from 7 YAML files

From YAML to a Running System

The YAML definitions are not just documentation — they're the contract between every component in your system. Here's how the definitions connect to a running fn-uns deployment.

How Each Component Uses the Definitions

ComponentReads FromWhat It Does With It
uns-sim (simulator) config.yaml (derived from site.yml) Generates realistic machine data for every equipment and sensor defined. The simulator's config mirrors the site hierarchy — areas, machines, sensors, programs.
uns-framework MQTT wildcard v1.0/# Subscribes to the entire namespace. The topic structure defined in uns.yml determines what the framework sees. New machines appear automatically — no configuration change needed.
uns-state / uns-historian Valkey cache + PostgreSQL The cache keys and database columns follow the topic structure. The YAML defines the namespace; the functions process whatever appears in it.
uns-input config.yaml The operator input screen is configured with YAML — reason codes, categories, theme colours, API endpoints. Same pattern: describe what you want, the system implements it.
Dashboards PostgreSQL queries Dashboard queries reference the topic structure. The YAML definitions ensure consistent naming — the dashboard knows that cnc-01 in the database matches cnc-01 in the YAML.
New developers The YAML files directly A new team member opens site.yml and immediately understands the factory structure — what machines exist, where they are, what data they produce. No tribal knowledge required.
The "describe what you have" philosophy is borrowed directly from infrastructure as code. Just as a Dockerfile doesn't run your application — it describes how to build the container that runs it — the UNS Framework YAML doesn't run your factory. It describes the factory so that every tool, function, and person can work from the same shared understanding. The YAML is the map; the running system is the territory.
Source: UNS Framework Standard v1.0; inspired by Docker, Kubernetes, and Terraform design principles
🔧

Manufacturing Engineer

When you add a new machine to the shop floor, you add it to site.yml. That single change propagates everywhere — the simulator generates data for it, the framework processes it, the dashboard shows it. One file, one change, one source of truth.

💻

Developer

You're building a new function and need to know the topic structure? Open uns.yml. Need to know what sensors exist on cnc-01? Open site.yml. Need the database connection? Open database.yml. Everything is documented, parseable, and version-controlled. No more "ask Dave."

🖥️

IT Engineer

Deploying to a new site? git clone the repository, update the site-specific values in the YAML files (broker address, database credentials, site name), and docker compose up. The entire namespace is defined in the files — no manual broker configuration, no manual topic setup.

Scaling to Multiple Sites

The real power of YAML definitions becomes clear when you scale beyond a single site. Adding a second factory is not a new project — it's a new set of YAML files in the same repository.

Adding a Second Site

# site.yml — now with two sites

version: '1.0'

# Templates are shared across all sites
template_sensor_cnc: &template_sensor_cnc
  information_model:
    status: { data_type: string }
    spindle_speed: { data_type: float }
    feed_rate: { data_type: float }
    program: { data_type: string }
    tool: { data_type: string }
    spindle_load: { data_type: float }

site:
  # ── Site 1: Detroit ──────────────────────────────────────
  - name: Detroit
    id: detroit
    location: 'Detroit, MI, USA'
    area:
      - name: Machining
        id: machining
        line:
          - name: CNC Line 1
            id: line1
            cell:
              - name: Cell A
                id: cell-a
                equipment:
                  - id: 'cnc-01'
                    name: 'Haas VF-2 Mill'
                    sensors:
                      - id: 's1'
                        <<: *template_sensor_cnc
                  - id: 'cnc-02'
                    name: 'DMG Mori NLX 2500'
                    sensors:
                      - id: 's2'
                        <<: *template_sensor_cnc

  # ── Site 2: Munich ───────────────────────────────────────
  - name: Munich
    id: munich
    location: 'Munich, Bavaria, Germany'
    area:
      - name: Precision Machining
        id: precision
        line:
          - name: 5-Axis Line
            id: 5axis
            cell:
              - name: Cell 1
                id: cell-1
                equipment:
                  - id: 'cnc-10'
                    name: 'DMG Mori DMU 50'
                    sensors:
                      - id: 's10'
                        <<: *template_sensor_cnc
                  - id: 'cnc-11'
                    name: 'Hermle C 400'
                    sensors:
                      - id: 's11'
                        <<: *template_sensor_cnc

The git diff for this change tells the whole story:

# git diff site.yml

+ # ── Site 2: Munich ───────────────────────────────────────
+ - name: Munich
+   id: munich
+   location: 'Munich, Bavaria, Germany'
+   area:
+     - name: Precision Machining
+       ...

# git log --oneline
b7e4a2f Add Munich site — 5-axis line with DMU 50 and Hermle C 400
a3f2c1d Initial Detroit site — 2 CNCs in Cell A

Multi-Site Topic Namespacing

Because the site ID is part of the topic path, topics from different sites are naturally namespaced:

# Detroit topics
v1.0/detroit/machining/line1/cell-a/cnc-01/s1/status
v1.0/detroit/machining/line1/cell-a/cnc-02/s2/status

# Munich topics
v1.0/munich/precision/5axis/cell-1/cnc-10/s10/status
v1.0/munich/precision/5axis/cell-1/cnc-11/s11/status

# Subscribe to everything at one site
v1.0/detroit/#

# Subscribe to everything across all sites
v1.0/#

Without YAML Definitions

Adding a second site means: fly someone to Munich, manually configure the MQTT broker, manually set up the SCADA tags, manually create the database tables, manually build the dashboards, hope the naming conventions match Detroit, document everything in a spreadsheet that will be outdated by next month.

With YAML + GitOps

Adding a second site means: add a new site entry to site.yml, commit, push. The templates guarantee the same information model. The topic structure guarantees consistent naming. The git history documents when Munich was added and by whom. Deploy with git clone + docker compose up.

MULTI-SITE YAML DEFINITIONS — ONE REPO, MANY FACTORIES Git Repository uns.yml · site.yml · mqtt.yml · function.yml git clone git clone Detroit 2 CNCs · 1 env sensor · 3 functions same YAML, same standard ✓ Munich 2 5-axis CNCs · 3 functions same YAML, same standard ✓ Site 3 — Future add to site.yml · git push same templates, same standard Shared templates guarantee consistency. Git guarantees traceability. YAML guarantees readability.

The Bottom Line

Your factory has a structure. Today, that structure is described inside vendor databases, spreadsheets, and people's heads — fragmented, unversioned, and impossible to reproduce. The UNS Framework standard gives you a better way.

PropertyMonolithic Vendor ToolsUNS Framework YAML
Source of truth Scattered across 6+ systems, each with a partial view One set of YAML files in a git repository
Version control None — changes are invisible and untrackable Full git history — every change has an author, date, and reason
Portability Locked in vendor-specific binary formats Plain text YAML — readable by any tool, any language, any platform
Reproducibility Manual configuration at each site, each time git clone → identical factory definition, instantly
Collaboration "Ask Dave" / check the spreadsheet on the shared drive Pull requests, code review, comments in the YAML itself
Automation Manual updates across multiple systems for every change Tools parse the YAML and act on it — topics, configs, dashboards derived automatically
Auditability No trail — "who changed the tag name?" is unanswerable git log + git blame — cryptographically signed, immutable history
Multi-site scaling Months of manual configuration per site Add a site entry to site.yml, push, deploy. Templates guarantee consistency.
Cost Vendor licenses per site, per device, per user Free — open standard, open source, plain text files
The UNS Framework standard is a Dockerfile for your factory. It doesn't replace your SCADA, MES, or MQTT broker — it describes what you have in a portable, version-controlled, human-readable format that becomes the single source of truth for your entire manufacturing namespace. Start with one site, one area, a few machines. The YAML grows with you.

Next Steps

ResourceDescription
UNS Framework StandardThe complete standard documentation — every definition type, every parameter, every schema
Core DefinitionsDetailed reference for all 13 definition types
Full ExampleA complete example deployment with all YAML files and generated MQTT topics
Digital Twins & GitOpsHow YAML definitions and GitOps enable composable digital twins
Flow vs GitOpsWhen to graduate from Node-RED experiments to production GitOps
Getting StartedDeploy the fn-uns reference pipeline — see the YAML definitions in action

Guide Version: 1.0 · Applies To: UNS Framework Standard v1.0, YAML definitions, GitOps, ISA-95 topic hierarchy

Last updated March 2026.