# ersioning Business Semantics for Enterprise AI

> Source: <https://dev.to/arisyndata/ersioning-business-semantics-for-enterprise-ai-2gcm>
> Published: 2026-09-24 23:05:00+00:00

**Your SQL can be perfectly reproducible while your business meaning is not.**

Suppose a user asks:

What was revenue in Q1?

Your data agent resolves `Revenue`, generates valid SQL, executes it successfully, and returns a number.

Now suppose Finance changed the definition of Revenue in June.

The old definition was:

```
Revenue v3
=
Recognized Revenue
```

The new definition is:

```
Revenue v4
=
Recognized Revenue
- Approved Adjustments
```

When the same user asks about Q1 in September, which definition should the agent use?

That is not an SQL problem.

It is a **semantic versioning problem**.

Enterprise data agents need more than a mapping from:

```
Business Term → Metric
```

They increasingly need:

```
Business Term
      ↓
Metric
      ↓
Version
      ↓
Effective Time
      ↓
Approval State
      ↓
Physical Mapping
```

If business meaning changes over time, the semantic layer needs a lifecycle.

**Why a Static Semantic Layer Breaks Down**

A basic semantic registry might store:

```
{
  "id": "revenue",
  "name": "Revenue",
  "field": "finance_revenue.recognized_amount",
  "aggregation": "SUM"
}
```

That works until the definition changes.

If the object is simply overwritten, you lose important information:

```
What was the previous definition?
When did the change become effective?
Who approved it?
Which answers used the old definition?
Should historical periods use the old or new logic?
```

A production semantic object should therefore be treated more like a versioned artifact than a mutable label.

**Model Semantic Objects as Immutable Versions**

One useful pattern is to separate the stable identity of a business concept from its versions.

```
Metric Identity
revenue
   │
   ├── v1
   ├── v2
   ├── v3
   └── v4
```

For example:

```
{
  "metric_id": "revenue",
  "version": 4,

  "definition": "Recognized revenue after approved adjustments",

  "expression": {
    "type": "formula",
    "value": "recognized_revenue - approved_adjustments"
  },

  "owner": "finance",

  "status": "published",

  "effective_from": "2026-06-01",

  "effective_to": null
}
```

Do not mutate `v3` into `v4`.

Create a new version.

That preserves historical meaning.

**Separate Version Time From Business Time**

This is where implementation gets interesting.

There are at least two relevant timelines.

When was the semantic definition created or published?

```
created_at
published_at
deprecated_at
```

When is the definition supposed to apply?

```
effective_from
effective_to
```

These are not always the same.

Finance might approve a new metric definition on June 10 but make it effective from June 1.

So a semantic object may need:

```
{
  "published_at": "2026-06-10T09:00:00Z",
  "effective_from": "2026-06-01",
  "effective_to": null
}
```

This distinction is essential for historical queries.

**Resolve Semantics With Time Context**

A semantic resolver should not simply do:

```
metric = registry.get("revenue")
```

It needs temporal context.

Conceptually:

```
metric = registry.resolve(
    metric_id="revenue",
    effective_at=query_time
)
```

For a question like:

What was revenue in January?

the pipeline becomes:

```
Question
      ↓
Intent Resolution
      ↓
Metric = Revenue
      ↓
Time Context = January
      ↓
Applicable Semantic Version
      ↓
Physical Mapping
      ↓
Query Plan
```

This is **version-aware semantic resolution**.

**But Historical Queries Have Two Meanings**

There is an important complication.

When someone asks:

What was Revenue in January?

they may mean:

Calculate Revenue using the definition that was valid in January.

or:

Calculate January data using today's Revenue definition.

These can produce different numbers.

So your semantic system may need an explicit policy:

```
{
  "historical_metric_policy": "as_was"
}
{
  "historical_metric_policy": "restated"
}
```

In some environments, the right answer may depend on the metric itself.

If the system cannot determine the intended policy safely, clarification may be better than silently guessing.

**Comparison Queries Are Harder**

Now consider:

Compare Q1 and Q3 Revenue.

Suppose the definition changed in Q2.

If you use each period's historical definition:

```
Q1 → Revenue v3
Q3 → Revenue v4
```

the comparison may not be semantically consistent.

If you restate both periods using v4:

```
Q1 → Revenue v4
Q3 → Revenue v4
```

the comparison is consistent, but it no longer represents exactly what the organization reported in Q1.

This decision belongs in business governance.

The LLM should not invent the policy.

**Version More Than Metrics**

Metrics are the obvious case, but other semantic objects can change too.

```
"Active Customer"
```

may change definition.

```
"Product Code"
→ product_master.material_id
```

may later become:

```
"Product Code"
→ product_dim.product_code
Region
Business Unit
Product Category
Customer Segment
```

can change structure.

```
Valid Order
Eligible Customer
Completed Transaction
```

can change inclusion logic.

If a change can alter analytical results, it should be traceable.

**A Generic Semantic Version Model**

You can model semantic objects with a shared envelope:

```
{
  "object_id": "metric.revenue",
  "object_type": "metric",
  "version": 4,

  "lifecycle": {
    "status": "published",
    "owner": "finance",
    "approved_by": "finance_governance"
  },

  "validity": {
    "effective_from": "2026-06-01",
    "effective_to": null
  },

  "provenance": {
    "created_at": "2026-05-28T08:12:00Z",
    "published_at": "2026-06-10T09:00:00Z",
    "previous_version": 3
  },

  "payload": {
    "definition": "...",
    "expression": "...",
    "physical_mapping": "..."
  }
}
```

The `payload` differs by semantic object type.

The lifecycle and provenance model can remain consistent.

**Add Lifecycle States**

Versioning alone is not governance.

A new definition should not automatically become production truth.

A useful lifecycle might be:

```
Draft
  ↓
Review
  ↓
Validated
  ↓
Published
  ↓
Deprecated
```

This prevents a work-in-progress definition from being used by production agents.

```
{
  "metric_id": "gross_margin",
  "version": 5,
  "status": "draft"
}
```

should not automatically replace:

```
{
  "metric_id": "gross_margin",
  "version": 4,
  "status": "published"
}
```

in production query resolution.

**Controlled Rollout Matters**

Sometimes a semantic change needs to be tested before becoming the default.

```
Gross Margin v5
      ↓
Test Workspace
      ↓
Selected Users
      ↓
Validation
      ↓
Production
```

This is similar to feature rollout in software systems.

The semantic definition itself becomes a governed production artifact.

A platform such as Semora already treats business semantic definitions, mappings, metrics and dimensions as governed objects alongside version and controlled-release management. That is the right architectural direction: meaning needs lifecycle management, not just storage.

**Define Material vs. Non-Material Changes**

Do not create a new analytical version for every edit.

A typo fix:

```
"recgonized revenue"
→
"recognized revenue"
```

does not change analytical behavior.

A formula change does.

A practical classification:

```
NON-MATERIAL
- spelling
- description wording
- examples
- documentation

MATERIAL
- formula
- aggregation
- source field
- semantic mapping
- filter rule
- inclusion/exclusion logic
- hierarchy
```

Only material changes need to create a new analytical version.

You can still audit non-material edits separately.

**Compute a Semantic Diff**

When a new version is created, show what changed.

Example:

```
Revenue v3 → v4

- expression:
-   recognized_revenue

+ expression:
+   recognized_revenue - approved_adjustments

+ effective_from:
+   2026-06-01
```

For mappings:

```
Product Code v1 → v2

- product_master.material_id
+ product_dim.product_code
```

A semantic diff is much easier to review than comparing two large JSON objects manually.

**Dependency Analysis Before Publishing**

Semantic objects rarely exist alone.

Suppose:

```
Gross Margin
```

depends on:

```
Revenue
```

If Revenue changes, downstream metrics may be affected.

Represent dependencies:

```
Revenue
   ↓
Gross Profit
   ↓
Gross Margin
```

Before publishing Revenue v4:

```
Change
  ↓
Dependency Graph
  ↓
Impacted Metrics
  ↓
Validation
  ↓
Publish
```

This is where semantic governance begins to resemble software dependency management.

**Keep Semantic Versions in the Query Plan**

Once a version is resolved, preserve it.

A semantic query plan should not contain only:

```
{
  "metric": "revenue"
}
```

Prefer:

```
{
  "metric": {
    "id": "revenue",
    "version": 4
  }
}
```

Then downstream stages know exactly which meaning was selected.

**Persist Versions Into Answer Lineage**

The final answer should preserve the semantic version that produced it.

```
{
  "answer_id": "ans_9281",

  "question": "What was revenue in Germany in July?",

  "semantic_evidence": {
    "metric_id": "revenue",
    "metric_version": 4,
    "mapping_version": 2
  },

  "query_id": "q_18273"
}
```

Six months later, you can reconstruct the answer even if Revenue has moved to v5.

This is **reproducible meaning**.

**Why SQL Versioning Is Not Enough**

Imagine storing the generated SQL:

```
SELECT SUM(recognized_amount - adjustment_amount)
FROM finance_revenue;
```

That tells you what executed.

But it does not necessarily tell you:

```
Why this expression represented Revenue
Which business definition authorized it
Who owned that definition
When it became effective
```

SQL provenance and semantic provenance solve different problems.

Production AI analytics needs both.

**Cache Carefully**

Semantic versioning also affects caching.

A cache key like:

```
hash(question)
```

is unsafe if the semantic definition changes.

A better cache identity may include:

```
Question
+
Semantic Version
+
Data Source Version / Freshness
+
Policy Context
cache_key = hash(
    question,
    metric_version,
    mapping_version,
    policy_version
)
```

Otherwise the system can return an answer generated under outdated semantics.

**Version-Aware Retrieval**

If semantic retrieval uses embeddings, versioning creates another issue.

Suppose both:

```
Revenue v3
Revenue v4
```

exist in the semantic index.

The retriever should not blindly return whichever vector is closest.

Retrieval needs governance filters:

```
semantic_search(
    term="revenue",
    status="published",
    effective_at=query_time
)
```

Similarity identifies candidates.

Governance determines which candidate is valid.

**Audit Every Semantic Resolution**

For production use, log:

```
{
  "question_id": "qst_182",
  "term": "revenue",
  "resolved_object": "metric.revenue",
  "resolved_version": 4,
  "effective_at": "2026-07-15",
  "resolution_source": "semantic_registry"
}
```

This makes semantic decisions observable.

If an answer is disputed, you can inspect exactly which definition the system used.

**A Reference Resolution Pipeline**

Putting the pieces together:

```
Natural-Language Question
          ↓
Intent Resolution
          ↓
Business Concept
          ↓
Extract Time Context
          ↓
Semantic Registry
          ↓
Filter:
- published
- effective at time
- allowed for user
          ↓
Resolve Version
          ↓
Resolve Physical Mapping
          ↓
Relationship Context
          ↓
Semantic Query Plan
          ↓
SQL
          ↓
Answer
          ↓
Answer Lineage
```

The LLM does not decide which semantic version is authoritative.

The governed semantic layer does.

**What to Test**

Semantic versioning needs its own test cases.

```
Question:
What is Revenue this month?

Expected:
Latest published effective version
Question:
What was Revenue in January?

Expected:
Historical version or governed restatement policy
Question:
Compare Q1 and Q3 Revenue.

Expected:
Explicit comparison policy
Revenue v5 = draft

Expected:
Production agent does not use it
Product Code v1 = deprecated

Expected:
New queries use the published replacement
```

These are semantic correctness tests, not SQL syntax tests.

**What to Measure**

Useful operational metrics include:

```
% queries using published semantic objects
% answers with semantic version lineage
Semantic resolution failures
Queries affected by semantic changes
Deprecated-version usage
Average approval time for material changes
```

These help teams operate the semantic layer as production infrastructure.

**Final Thoughts**

Enterprise AI cannot treat business meaning as a static prompt.

Metrics change.

Mappings change.

Business rules change.

Dimensions change.

And historical questions still need to remain explainable and reproducible.

The architecture therefore needs to move from:

```
Term → Definition
```

to:

```
Term
 ↓
Governed Semantic Object
 ↓
Version
 ↓
Effective Time
 ↓
Approval State
 ↓
Physical Mapping
 ↓
Query
```

The key engineering principle is:

Because a perfectly reproducible SQL query can still produce the wrong business answer if the system cannot reproduce the meaning that was valid when the question was asked.
