Skip to content

Semantic models: describe your warehouse once

A semantic model is a governed description of one warehouse connection: its tables, the fields people ask about, and how the tables join. A reviewer approves each version before it goes live, so the live description is always an approved one.

Describes1 connection per model
Live versionReviewed before it goes live
Join depth3 hops max
Lifecycledraft · review · live · archived

When to choose this

  • One description of your tables


    Name each table once, label the fields people ask about, and say how the tables join, instead of every report rediscovering it.

  • A reviewed version is the live one


    An editor changes a draft. An approver reviews it as a task, and only then does it replace the live version.

  • Every version is kept


    Open any earlier version, or compare two, and see exactly which tables, fields and joins changed.

  • The words people actually use


    Give each field a label, synonyms and a glossary term, and hide the columns nobody should ask about.

When not to reach for a semantic model

  • A single KPI calculation → define a metric.
  • A one-off query → write it in Insights.
  • dbt's own semantic models → those are read from your dbt manifest by the Metadata Engine; this page is about the models you govern in Datahub.

How it works

flowchart LR
    CONN["Warehouse connection"] --> MODEL["Semantic model<br/>name · description"]
    MODEL --> DRAFT["Draft version<br/>tables · fields · relationships"]
    DRAFT -->|Submit for review| REVIEW["Under review<br/>a task for an approver"]
    REVIEW -->|Approve| LIVE(["Live version"])
    REVIEW -->|Reject or withdraw| DRAFT
    classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
    class LIVE accent

Figure 1 — A model describes one connection. Editors change a draft, an approver reviews it, and the approved version replaces the live one.

Why teams use it

Without a shared description, every report decides for itself which column is the customer key and how orders join to customers. A semantic model makes that decision once, in review, and keeps the history of every change.

What reads the live version

A report can use a model so that one page filter on a field reaches every card the relationships connect to it: see filters on a semantic model's fields. Herc and the MCP tools read the live version, never a draft, when they write a query that joins tables: see How the assistant reads a model.

Concepts

Concept What it is
Model The name, description and warehouse connection. The connection is fixed when you create the model; describing another connection is a new model.
Version One complete description of the tables, fields and relationships. Versions are numbered v1, v2, and so on.
Draft The version editors change. A model has at most one draft.
Under review A version submitted for approval. A model has at most one version in review, and its definition cannot change while it is there.
Live version The approved version everything reads. Approving a new version replaces it, and the old one is kept as superseded.
Table A warehouse table, named by catalog, schema and table, with its primary key.
Field A column of a table, with a label, synonyms, an optional glossary term, a hidden flag, and its role in model cards: a dimension, or a time field at a grain.
Relationship How two tables join: the join columns, the cardinality (many to one, or one to one), where it came from, and whether it is active.

Using the pages

The Semantic models entry sits in the Insight group of the sidebar, next to Metrics.

  1. Find a model. The list shows every model with its connection, its governing domain, the status of its latest version, its live version, when it was last published and how many reports use it. Search by name, filter by status, and switch to the archived view to see archived models.
  2. Create a model. Choose New semantic model, give it a name, pick the warehouse connection it describes, and pick its governing domain. The model starts with an empty draft, v1.
  3. Read a version. Open a model to see its governing domain, its connection, its tables and fields, and its relationships. Three views show the version: Diagram (the default), Tables and Relationships (see the three views). The page opens the version in review, else the draft, else the live version. Choose another version in the version rail on the right.
  4. See what changed. When you view a version that is not live, the page shows its changes against the live version. Use Compare in the version rail to diff any two versions. The comparison shows a measure's description, and the glossary term a measure or a field points at, by the term's name. While a name loads it reads "loading"; a term you may not open reads "a term you can't open", and a term that no longer exists reads "unknown term".
  5. Submit for review. When the draft is ready, choose Submit for review. The review becomes a task for an approver. While it is open you can withdraw it, and the version becomes a draft again.
  6. Approve. An approver opens the review task from the model page or from Tasks and approves or rejects it. You cannot approve your own submission.

A model belongs to a governing domain

The governing domain decides who reviews the model, so a model has to be filed in one before it can be submitted.

  • On create. The Governing domain field lists the domains you are a member of. It is required as long as you are a member of at least one. If you are a member of none, the form still saves, and the model stays unfiled until someone who is can file it.
  • On the model page. The Domain slot in the header names the domain. With semanticmodel.manage, press Choose on an unfiled model, or Change on a filed one, to file the model or move it to another domain you are a member of. Choosing no domain takes the model out of its domain. Refiling forks no version.
  • Why Submit waits. Submit for review stays greyed out on an unfiled model, and the header says why. A server check backs this up: submitting an unfiled model is refused with governing_domain_required. File the model and the button is available again.
  • Who may change a filed model. Once a model is filed, only members of its domain can save, archive, restore or submit it. Every filing and refiling is written to the audit log.

Every save checks the Metadata Engine

A save checks the draft's tables, columns and keys against what the Metadata Engine harvested from the connection. A table it has not harvested or no longer finds, a column it did not see, or a key it does not know is refused by name. A table you add gets its primary key from the engine, and a relationship that joins onto a key the engine knows stores that key. A save never queries the warehouse.

A draft must be publishable

Submit checks the draft first. It needs at least one table, every relationship must join to the primary key or a unique key of the table it points at (a one-to-one relationship on both sides), and no two tables may be joined by more than one active path within three hops. Submit then checks the tables and columns on the warehouse itself. A refusal names the table or relationship to fix, and the page lists each problem under it (see Fixing a refusal).

Formula measures

A formula measure is a calculation over the names of other measures of the same model, such as revenue - cost or round(profit / revenue * 100, 1). A formula can read a simple measure, a ratio or another formula. Cards, metrics and the assistant use it like any other measure, and the metric engine computes it, so every consumer gets the same number.

  • Operators and functions. A formula may use plus, minus, times, divide, numbers, parentheses, and the functions coalesce, nullif, round, abs, greatest and least. Another function, a subquery, a table or column name, a comment or a second statement is refused on save, with the reason and the name of the measure.
  • Dividing by zero. A division by zero gives an empty value, not an error.
  • No loops. A formula cannot read itself, directly or through other formulas. A loop is refused on save.
  • Renaming, removing, re-kinding. Renaming a measure renames it inside every formula that reads it. Removing a measure, or changing it to another kind, is refused on save while a formula reads it; change the formula first, in the same save if you like.

The Measures table shows a formula with its text. Writing a formula in the editor is not available yet; an assistant with the model authoring tools can add one and change it.

Reports that use a model

A report that uses a model filters its cards through the model's fields and relationships (see filters on a semantic model's fields). A new version or an archive can break those filters, so the model's pages name the reports that depend on it.

  • Reports using it. The list counts, per model, the reports with a live version, a version in review or a draft that uses it. A report counts once.
  • Before you submit. The Submit for review dialog lists each report whose page filters the draft would break, and why:

    • the filter's table or field is not in the new version;
    • its field is hidden;
    • a relationship it travels is removed or made inactive.

    A renamed label breaks nothing. When nothing breaks, the dialog says how many reports it checked. - During review. While the version is in review, the model page shows the approver the same list. - Alerts on the model. An alert that watches a measure of the model runs on the model's live version. The same dialog, and the approver's list, name each alert whose measure the new version removes, with whom to ask: its owner, or whoever created it when it has no owner. When that person can no longer sign in, the list says so: anyone who can edit alerts can take it over. A paused alert or one that is not active yet is named too, marked as such: it fails once it is resumed or activated. An archived alert is not named. Without logicengine.rules.read, an alert is named without a link. - It warns, it never blocks. Submit and approve still go ahead. Once the version is live, the report's cards say the filter's field was removed from the model and are no longer narrowed by it, until the report is updated. - Archiving. A model that a live report uses can't be archived. The archive dialog names those reports and Archive stays greyed out: publish each report without the model first. Report drafts and reports in review that use the model don't block the archive. They are named when it is done, because their model filters stop working. - Reports you can't open. Without insights.read, a report is named without a link.

Editing a model in the diagram

A model's page draws its tables as a diagram. Each table card lists its fields and marks the key columns. Each line is a relationship: it shows its cardinality (1:N or 1:1), and its arrow points the way a filter flows, from the one side to the many side. An inactive relationship is dashed. A table, field or line that a refusal names is drawn red.

The three views

Above the model, three tabs switch the view. The tabs for tables and relationships show a count.

  • Diagram. The tables and the lines that join them.
    • Move a table: drag its card.
    • Keep your arrangement: where you drop each table is kept in your browser for that model, so it is still there when you come back (if your browser blocks storage, the diagram says so and the arrangement lasts until you leave the page). It is not part of the version: nobody else sees it, and arranging the diagram changes nothing that is saved or reviewed.
    • Controls (bottom right): zoom in, zoom out, fit every table in view, reset the tables to their starting positions, and full screen.
    • Overview map: for a model of more than eight tables, an overview map in the top right shows where you are. Drag in it to move around.
  • Tables. One row per table, with its warehouse name, how many of its fields are offered, its keys and how many relationships join it.
    • Expand a row to see its fields.
    • Search finds a table by its name or by any field's label, column or synonym. A table the search found through a field opens on just the fields that match.
    • Sort by any column. Long lists are paged.
  • Relationships. Every relationship, with its two sides, cardinality, source and whether it is active. Search by table or column, and filter by cardinality, source or active.

With semanticmodel.manage, clicking a row in Tables or Relationships opens the same editor as the diagram. Without it, clicking a table's row expands it.

With semanticmodel.manage, you edit the draft on the same page:

  1. Add table. Browse and search the tables the Metadata Engine harvested from the model's connection. A table comes in with all its columns hidden, so report builders and Herc see nothing of it until you offer fields. When nothing has been harvested, Add table says why and what to do next:

    • Databricks: each Metadata Engine connection that syncs the workspace, with its last sync (and why it failed), Open connection and Sync now. When no connection syncs it, Set up a connection.
    • PostgreSQL: the Metadata Engine connection for the model's database, with its last sync (and why it failed, or that the last sync could not be read, with Try again), Open connection and Sync now. When no connection covers it, Set up a connection. A finished sync lists its tables in the open picker without reopening it.
    • Fabric or Azure SQL: the integration's harvest card, with Harvest.
    • A connection type the engine does not harvest: it says so.

    Opening a connection or the harvest card needs Metadata Engine read; Sync now, Harvest and Set up a connection need read and write. Without them, it tells you to ask a Metadata Engine administrator. A finished sync or harvest lists its tables in the open picker.

  2. Choose the fields. Open a table card (click it, or Tab to it and press Enter), or its row in Tables. The table editor shows, from top to bottom: any problems, the table's label, its keys, the relationships that join it, and its fields.

    • Offer or hide a field: use its switch.
    • Offer every field at once: use the switch in the Offered column header. Switch it off to hide them all again. It acts on the fields the search and filter leave listed, on every page.
    • Find a field: search by label, column or synonym, or filter on offered or hidden.
    • Edit a field: open it to set its label and role in cards, link a glossary term and add synonyms.
    • Role in cards: the Role in cards column names what a model card does with each field. A date or timestamp column is a time field at day grain (Time · day), and every other column is a dimension to group and filter by. The role comes from the column type the Metadata Engine harvested. In the field's editor you can make it a dimension or a time field and pick its grain (day, week, month, quarter or year). A role you set is marked Set by a steward, and Reset to the column type gives the column type back its say. A role you set or reset is read again on the next save. Until then, a reset field says the save decides it. A save refuses a time role on a column that is not a date or timestamp, and lists that problem at the top of the field's editor.

    Esc closes the editor. 3. Accept proposals. The Proposals panel lists the joins the warehouse metadata suggests for the tables in the model, grouped by source: Unity Catalog foreign keys, the entities of your dbt semantic models, and the joins Genie's constraint analysis finds. Accept adds the relationship and records where it came from; Ignore hides the proposal until you reload the page. When the proposal's one side is not a primary key the Metadata Engine knows, the cardinality is not known, and the proposal says so: Accept then opens the relationship editor with the join filled in and asks you to pick the cardinality before it is added. A foreign key onto a table the model does not have yet is listed under Tables to add, with its own Add table. When a source has nothing to offer, the panel says why: you have no access to its metadata, nothing has been harvested from it for this connection, or it could not be read this time. 4. Draw a relationship. Add relationship, or click a line to edit it: pick the many side and the one side, pair up to four columns, set the cardinality, and switch it off to keep it as an inactive second path. 5. Save draft. A save writes the draft and checks it against the Metadata Engine. Proposals read the saved draft, so save after adding tables to see their joins.

  3. Two active paths. When two active relationships join the same tables, a warning above the diagram names both paths and draws their lines red before you submit. Make one of them inactive or remove it.

  4. Editing the live version. When the model has no draft, the page says first that your first save starts a new draft; the live version stays live until a review approves the draft.
  5. Unsaved changes. Leaving the page with unsaved changes asks first, and Submit for review waits until the changes are saved or discarded.
  6. Readers. Without semanticmodel.manage, or while a version is in review, the diagram is read-only.
  7. Keys. A table's editor lists its primary key and each unique key by column. A key column that is not one of the table's fields is marked (not a field): the Metadata Engine may know a key on a column you have not offered. A table without a primary key says what fills it: the next save, for a table added since the last save, or a relationship that joins onto a key the engine knows.

When someone else saved the draft first

A model has one draft. If a colleague saves it while you edit, your save is refused, and a notice stays on the page above your edit, which stays as you left it, unsaved. The notice names their draft and offers three choices:

  • Save draft again replaces their draft with yours.
  • Compare shows what the replacement changes: their draft against your edit.
  • Discard drops your edit and shows their draft instead.

Nothing is replaced until you choose Save draft again.

Fixing a refusal

When a save or submit is refused, the page lists each problem under the table, relationship or path it is about, with the model's own problems first. A field's problem is listed under its table.

  • Open takes you to that table or relationship. Its editor lists the same problems at the top.
  • After an edit, the list stays and says you have edited the draft since. Save again to check.
  • A table or relationship you removed since the refusal stays listed, marked as gone, with nothing to open.
  • Store as a unique key. When a relationship joins onto columns its table does not store as a key, the list and the relationship's editor offer Store (columns) as a unique key of (table). The editor offers it until you change the join there. The click only changes the draft. The next save keeps the key only if the Metadata Engine knows it, and otherwise refuses it by name. This is how a key declared in the engine after your last save gets into the draft: saving an unchanged draft does nothing.

How the assistant reads a model

sequenceDiagram
    autonumber
    participant U as You
    participant H as Herc or an MCP client
    participant DH as Datahub
    U->>H: Revenue per customer segment?
    H->>DH: list_semantic_models (the connection)
    DH-->>H: The live models you may read
    H->>DH: get_semantic_model
    DH-->>H: Tables, keys, visible fields, relationships
    H-->>U: A query joined on the model's relationship
    Note over U,H: You read the query and apply it

Figure 2 — Before it joins two tables, the assistant reads the connection's live model and joins on the keys the model declares, not on columns that only share a name.

  • Only the live version. A model with only a draft, or an archived one, is refused as not published, and the assistant says so instead of reading the draft. Hidden fields are left out.
  • Join hints. When the assistant describes a table or a whole schema, the answer also lists the relationships the live models declare on those tables, so the join keys sit next to the columns. A schema lists each join once, active relationships first, and at most 60; describing one table lists every relationship it has.
  • One relationship per pair of tables. The assistant joins on all the columns of one relationship. When two relationships join the same tables (an order date and a ship date), it takes the active one unless your question means the other.
  • No model, no guessing in silence. Without a live model, or without semanticmodel.read, the assistant falls back to column names and says the keys were inferred. When the role is what is missing, it names semanticmodel.read so you know what to ask for.
  • Your connections only. Models on a connection you may not use are left out of the list and refused when asked for.
  • One domain. Ask about a domain and the assistant lists, reads and takes join hints from only the models filed in it. A model filed in another domain, in none, or in more than one is left out, and asking for it by name answers not found. Without a domain, every model you may read is in view.
  • Dashboards. A dashboard the assistant creates can be tied to a live model on the same connection. When it cannot be, the assistant says why: you do not hold semanticmodel.read, the model does not exist, is archived, has no live version yet, describes another connection, or its live version cannot be read.

Roles

Role What it allows
semanticmodel.read See the list, the models, their versions and their history. Herc and the MCP tools read live models with your roles, so they need it too.
semanticmodel.manage Create, rename, archive and restore models, change the draft, submit it for review, and withdraw a review.
semanticmodel.approve Approve or reject a version under review, from its review task.

Someone without semanticmodel.read does not see the sidebar entry, and opening the page directly shows that access is needed.

Limitations

Limitation Detail
Unique keys on the page A table's editor lists its unique keys, and a refused relationship offers to store its join columns as one. You cannot type in or remove a unique key on the page.
One connection A model describes one warehouse connection and cannot be moved to another.
Harvested connections A model's tables come from the Metadata Engine's harvest of its connection. A Fabric or Azure SQL connection is harvested when a Metadata Engine administrator clicks Harvest on its integration page. A Databricks or PostgreSQL connection is harvested when it has a Metadata Engine connection that has synced. Until a PostgreSQL connection has synced, Add table offers Set up a connection or Sync now.
Join depth A filter travels at most three hops along the relationships.

Audit & compliance

Question Answer
Who changed the model? Every create, edit, filing in a domain, submit, withdraw, approval, archive and restore is written to the module's audit log, shown in the platform activity log.
Which keys came from the Metadata Engine? A create or edit that filled in a key from the engine lists it on its audit row: the table, whether it is the primary key or a unique key, its columns and, when the engine records it, whether the key was harvested or declared by an administrator. A key the author sent is not listed.
Which version was live on a date? Each version records when it went live and when it was replaced.
Who approved it? An approved version names its approver. The submitter cannot approve their own version.
Can a model be deleted? No. A model is archived, never deleted, and its versions are kept.

Troubleshooting

Symptom Cause Fix
No New semantic model button You do not hold semanticmodel.manage. Ask an administrator for the role.
No connection to pick No warehouse connection is set up, or none you may use. Ask an administrator to connect a warehouse.
Submit for review is missing There is no draft, a version is already in review, or the model is archived. Withdraw the open review, or restore the model.
Submit for review is greyed out The draft has no tables yet, so there is nothing to review, or the model is not filed in a governing domain. Add at least one table to the draft, or press Choose on the Domain slot in the header.
The domain picker is empty You are not a member of any domain, so there is none you may file the model in. Ask a domain steward to add you, or to file the model.
Save says the engine has harvested no table from this connection The Metadata Engine has not harvested the connection: it is a Fabric or Azure SQL connection nobody has harvested yet, or a Databricks or PostgreSQL connection with no Metadata Engine connection or one that never synced. Open Add table: it shows the next step for this connection, such as Sync now with the last sync's failure, or Harvest. Without the Metadata Engine roles, ask a Metadata Engine administrator to sync or harvest the connection.
Save says the engine has not harvested a table, but has it in another spelling On PostgreSQL, Fabric and Azure SQL, the Metadata Engine matches a table's schema and name exactly as the harvest found them, so Sales.orders does not match Sales.Orders. Spell the table the way the message names it.
Save says a key is not a key the engine knows A primary key or unique key the draft stores is not a key in the Metadata Engine. Ask a Metadata Engine administrator to declare the key there, then save again.
Submit says a relationship's columns are not a key of a table The relationship joins onto columns the table does not store as a key. Join onto one of the table's keys, or press Store (columns) as a unique key under the relationship in the list or in its editor, then save. The save accepts the key once the Metadata Engine knows it.
Submit is refused The draft is not publishable, or a table or column is gone from the warehouse. Fix the table or relationship the message names.
Archive is greyed out, or archive is refused A live report uses the model. The dialog names it. Publish the report without the model, then archive.
You cannot withdraw a review Only the submitter, the assigned approvers or a tasks administrator may withdraw it. Ask one of them.
Herc says the join keys were inferred The connection has no live model, the model is only a draft, you do not hold semanticmodel.read, or the connection is outside your reach. Publish a model for the connection, or ask an administrator for the role or the connection.
A dashboard cannot be tied to a model The model is a draft, archived, on another connection, or you cannot read semantic models. Herc names which. Approve a version, pick the model of the dashboard's connection, or ask for semanticmodel.read.

See also

  • Metrics


    Governed KPI definitions on top of your tables.

  • Insights


    Live dashboards on your warehouse.

  • Tasks


    Where approvers find the review tasks.

  • Workflows


    How reviews are routed to approvers.