Semantic Layer
Define, browse, validate, and query your business metrics in one place. The dbdeux Semantic Layer sits on top of your dbt models: one governed definition of every metric, published as a pinned version, and served consistently to the app, your BI tools, your scripts, and your AI assistants.
Overview
The Semantic Layer lives in the left navigation under Semantic Layer. It reads semantic model definitions committed in your repository and presents them as a browsable catalog. Every metric, dimension, and dataset is visible at a glance with search and filtering.
The catalog shows a stats bar at the top with totals for semantic models, metrics, and dimensions across your project. Type-colored icons in the sidebar (purple for models, blue for dimensions, orange for metrics) make it easy to scan.
When no metric definitions exist yet, the page shows an animated empty state with a glowing emblem and floating chip hints to guide you toward defining your first semantic model.
Catalog Browser
The catalog sidebar lists all semantic models in your project. Expand any model to see its metrics, dimensions, measures, and datasets:
- Semantic models: Top-level groupings that map to your dbt models
- Metrics: Named calculations (revenue, order count, customer LTV) with their expressions
- Dimensions: Grouping and filtering attributes (date, region, status, category)
- Measures: The raw numeric fields that metrics aggregate over (amount, quantity, cost). Measures are the ingredients, metrics are the recipe, and separating them makes it clear where a number comes from
- Datasets: The underlying tables and relationships
Every section header carries an info icon explaining in plain language what that section contains and how it differs from the others, so a business user browsing the catalog does not need someone to explain the modelling vocabulary first.
Click any item to open the detail pane on the right.
Which Branch You Are Reading
Semantic definitions live in your repository, so what the catalog shows depends on the branch it is reading. A branch selector at the top of the page names the branch in view and lets you switch to another one without leaving the catalog, so you can compare what a feature branch defines against what production has today. It removes a genuinely confusing moment: a metric you just wrote is not missing, you are simply looking at a branch that does not have it yet. When you generate or import a definition, the page follows it onto the branch it was written to, so the thing you just created is on screen instead of a branch away.
Business Names First
Wherever a definition has a business label, the catalog leads with it and shows the technical name underneath. You read Total Revenue, not total_revenue_amt. The technical name is never hidden, so an analyst can still copy the exact identifier for a query, but nobody has to translate identifiers in their head to find what they need.
Browse by File
Projects usually spread semantic definitions across several files (marts, staging, finance, and so on). A file selector lets you browse one file at a time or search All files at once, so a large catalog stays navigable and you can review exactly what a single file contributes.
The sidebar can be dragged wider or narrower and remembers your choice, which matters when your names are long. On very wide tables, the group-by chips are capped with an expand control instead of flooding the pane with hundreds of dimensions.
Detail Pane
The detail pane shows full information about the selected item:
Metric Detail
- Expression: The calculation formula with syntax highlighting
- Source file: Which YAML file defines this metric
- Dimensions: Available grouping dimensions displayed as interactive pills
- Badges: the metric's owner, a
cumulativebadge with its rolling window where one applies, and a clear deprecated marker that names the replacement metric to use instead - Live SQL preview: Compile the metric to real SQL (see below)
- Preview data: Run the metric against your warehouse and see real rows (see below)
Model Detail
- Stats band showing dataset, metric, and relationship counts
- Quick navigation to any child metric or dimension
- Visual summary with type-colored badges
Dimension Detail
- Which dataset and model it belongs to
- Whether it is a time dimension
- Where it is referenced
Semantic View and Compiled SQL
A metric can be read two ways, and the detail pane offers both:
- Semantic: the governed definition in business terms. What is being measured, what it aggregates, which dimensions you can group it by, and who owns it
- Compiled SQL: the exact query your warehouse will run, including which datasets it touched and which dialect it was compiled for
That pairing is the point of a semantic layer. Business users can read the definition without SQL, engineers can verify the generated query, and both are looking at the same single definition rather than two documents that drift apart.
Live SQL Preview
Select a metric, pick your dimensions, and see the compiled SQL instantly. The preview adapts to your warehouse dialect:
| Dialect | Syntax adaptation |
|---|---|
| Snowflake | DATE_TRUNC('month', col) syntax, schema quoting |
| BigQuery | date_trunc(col, MONTH) syntax, backtick quoting |
| Redshift | Redshift-compatible SQL generation |
| Databricks | Spark SQL dialect support |
| PostgreSQL | Standard PostgreSQL syntax |
| Athena | Presto/Trino SQL dialect |
| StarRocks | MySQL-compatible syntax |
The SQL is compiled on demand. Change your dimension selection or dialect and the preview updates immediately.
Preview Data
Compiled SQL tells you what a metric would run. Preview data shows you what it actually returns. From the metric detail pane, pick an environment with a warehouse connection and click Run:
- Results come back as a table with the row count, how long the query took, and clear
NULLstyling - Large results are capped, with a plain notice telling you the output was truncated
- Only a single read-only
SELECTis ever executed, and it runs in an isolated session using your chosen environment's connection
This closes the loop that most metric layers leave open: you can sanity-check a definition against real numbers the moment you write it, without leaving the catalog or opening a SQL client.
Edit the SQL Before You Run It
Sometimes you want to poke at the query itself: add a filter, narrow a date range, or check an edge case before you commit the definition. Click Edit SQL and the compiled query becomes editable in place.
- The run button changes to Run edited SQL, so it is always obvious whether you are running the governed query or your own variation
- Edits go through exactly the same read-only safety checks as everything else. A single
SELECTis all that will ever run, no matter what you type - Reset to compiled SQL puts you back on the governed query in one click
- Your edit is a scratchpad only. It never changes the metric definition and is never reused as the published query
Most semantic layers treat compiled SQL as a black box you can read but not touch. Being able to tweak and re-run it in the same pane is the difference between debugging a definition in seconds and copying SQL into another tool to find out what went wrong.
Metric Types
Beyond straightforward aggregates, the Semantic Layer supports the metric shapes analytics teams actually need:
- Simple: the default. A single aggregate expression over a dataset
- Cumulative: a running total along the query's time dimension, or a rolling window when you set one (for example a
7 daytrailing total). The catalog badges these so nobody mistakes a rolling metric for a period total - Conversion (funnel): measures how many entities that did one thing went on to do another within a time window. You declare the base event and the conversion event, the window, and whether the metric outputs a conversion rate or a count of conversions
Time Grains and Complete Time Series
Any time dimension can be queried at a grain by adding a suffix, for example order_date__month. Supported grains are day, week, month, quarter, and year, and the grain is applied correctly for your warehouse dialect.
Two options make time series honest rather than misleading:
- Fill gaps: when you group by a single grained time dimension, dbdeux can generate the full date axis so periods with no data appear as real rows instead of silently disappearing from a chart
- Fill nulls with: a metric can declare the value to use when there is nothing to aggregate (commonly
0), so an empty period reads as zero rather than blank
Hierarchies and Drill-Downs
Declare a hierarchy as an ordered set of levels over dimensions you already have, from most aggregate to least (for example country, then state, then city). Once declared:
- Drill down one level at a time from any result, and dbdeux adds the right grouping for you
- Ragged hierarchies are supported, so taxonomies where an intermediate level is sometimes empty still roll up correctly
- Levels reference existing dimension fields, so a hierarchy never invents new data
Non-Additive Guardrails
Some metrics simply cannot be summed up a hierarchy. A distinct count of customers by city does not add up to the distinct count by country, and account balances do not add up across time. A metric can declare which hierarchies or grains it must not be naively rolled up along, and dbdeux respects that rather than quietly returning a wrong number. This is the kind of mistake that silently corrupts dashboards for months, and the semantic layer is where it should be caught.
Metric Governance
Metric definitions carry the metadata a team needs to trust and maintain them:
- Owner: who is responsible for the definition, shown as a badge in the catalog
- Deprecation: mark a metric deprecated with the date it was retired, the reason, and the metric to use instead. Consumers see the notice everywhere the metric appears, so migrations do not depend on tribal knowledge
- Visibility: mark a metric or dimension internal to keep it out of the catalog, the API, and AI tools, so building blocks that are not meant for general consumption stay out of everyone's way
- Display order: control the order metrics and dimensions are presented in, so the most important definitions surface first rather than falling in alphabetical order
Published Catalog Versions
A metric definition on someone's branch is a draft. Publishing turns the current state of your catalog into an immutable, validated version that everything else reads from.
- Click Publish to pin the current catalog as a new version. Publishing again with no changes is a no-op and tells you so, rather than piling up duplicate versions
- The API, AI agents, and Atlas all serve from a published version, so a dashboard, a co-pilot answer, and an API consumer cannot disagree about what "revenue" means
- Previous versions remain listed, so a consumer can pin to an exact version and be certain their numbers will not shift underneath them
Saved Queries
Name a metric query once, then reuse it. A saved query captures the metrics, dimensions, filters, grain, and ordering you selected, and can be listed and run later from the app or through the API. Instead of every consumer rebuilding the same question slightly differently, the question itself becomes governed alongside the metric.
Filtering on Metric Values
Alongside dimension filters, queries support having filters that filter on the metric's value itself, for example only regions where revenue exceeded a threshold. dbdeux resolves these correctly for every supported warehouse dialect.
Query History
Every metric query the project runs is recorded, so the semantic layer has a memory. Open the Semantic Layer menu and choose Query history to see what has been asked, by whom, and what came back.
The list is newest first and covers every way a metric can be queried, each labelled so you can tell them apart:
| Where the query came from | Shown as |
|---|---|
| Someone previewing a metric in the catalog | Preview |
| A saved query being run | Saved query |
| A tool reading through the GraphQL interface | GraphQL |
| An AI assistant using the agent interface | MCP |
Expand any entry to see the whole story of that query: the metrics and grouping that were asked for, the filters applied, the SQL that was generated, how long it took, how many rows came back, whether the result was truncated, and the catalog version it was answered from.
Succeeded, Cached, or Failed
Each entry carries an outcome, and the distinction is the useful part:
| Outcome | What it means |
|---|---|
| Succeeded | The query ran in your warehouse and returned rows |
| Cached | The answer was already known for that pinned catalog version, so your warehouse was never queried |
| Failed | The query did not complete, and the entry keeps the exact error so you can see why |
Failed attempts are kept deliberately. Most metric tools only remember the questions that worked, which is exactly the wrong half: when a dashboard or an agent gets an error, the attempt has usually vanished by the time anyone goes looking. Here the failed attempt is still listed, with its SQL and its error message, so you can tell a mistyped dimension apart from a warehouse problem without asking the person to reproduce it.
Run It Again
Any entry has a Run again button that replays the same question. Reruns go through the normal path, so they are validated and executed exactly like a fresh query rather than replaying a stored answer, and the new result appears inline underneath the entry.
This is what turns history into a working tool rather than an audit trail. "It returned the wrong number this morning" becomes a single click, and you either see the same number, or you see that it changed and which catalog version each answer came from.
Query Metrics from Anywhere
The semantic layer is not just a UI. Governed metrics are reachable programmatically, always from a published version:
- Public API: read the published catalog, list versions and saved queries with the
semantic:readscope, and execute ad hoc or saved metric queries with thesemantic:queryscope. See Service Accounts and API - GraphQL: for tools and front ends that already speak GraphQL, the semantic layer exposes a single GraphQL interface over the same governed definitions. One request can discover metrics and dimensions, list saved queries, and run a metric query, asking for only the fields you actually need instead of stitching several calls together. Queries accept the branch and the catalog version to read from, plus the environment, row limit, and timeout, so a tool can pin itself to an exact published version
- AI assistants: assistants such as Claude and Cursor can connect to dbdeux directly and ask a governed metric instead of writing speculative SQL, using the same
semantic:readandsemantic:querypermissions. Their questions are answered from the published definition, so an assistant and a dashboard give the same number. See AI Assistants
Whichever route a query takes, it lands in the same query history with its source labelled, so a metric that suddenly returns something odd can be traced back to what asked for it.
This matters because it makes the semantic layer the single answer to "what is revenue?" no matter who is asking: a person in the app, a script, a BI tool, or an AI assistant. Assistants in particular stop inventing SQL against raw tables and start using definitions your team actually governs.
Editing a Semantic Model
Definitions are files in your repository, and dbdeux gives you a proper editor for them without sending you off to hunt down the YAML. Open any model and choose Edit to get one definition with three ways to work on it, all editing the same file.
Builder: No YAML Required
The Builder view presents the model as structured forms: datasets, relationships, metrics, and hierarchies, each with add, edit, and remove controls. Fill in fields, pick from dropdowns of what already exists, and the YAML is written for you.
This is what lets a semantic layer be a team asset rather than an engineering asset. An analyst who knows the business definition of a metric can add it correctly without learning the file format first, and without pinging an engineer to translate a Slack message into YAML.
Your comments and any fields the form does not touch are preserved exactly, so a hand-written file does not come back reformatted or stripped of the notes your team left in it.
YAML: Full Control When You Want It
The YAML view is a real code editor over the same file, with:
- Field completion for the definition format, so you are not guessing at key names
- Hover help explaining what a field means
- Syntax problems flagged as you type
- Validation results marked on the exact offending line rather than reported as a message you have to go and find
Switching between Builder and YAML never loses work. They are two views of one file, not two copies.
Edit with Atlas
Describe the change in a sentence, for example "add a total revenue metric summing orders.amount" or "join orders to customers on customer_id". Atlas proposes the updated definition and shows you a diff against your current file.
Nothing touches the file until you apply the proposal, and nothing touches your branch until you save. AI is used to draft a change you review, never to quietly rewrite a governed definition.
Validate, History, and Restore
- Validate model checks the unsaved file against the definition rules and reports every issue with its location, so you find problems before a run does
- History lists the commits that touched this file. View any earlier version, and restore it as a normal working change you can review and commit. Restoring is always reversible, because it is just another edit
- Save to branch validates first, then writes the change as an uncommitted working change on your branch. Publishing stays a separate, deliberate step, so saving a draft never changes what your dashboards and API consumers are reading
Metric Diff (Compare)
Compare metrics between branches to catch breaking changes before they merge:
- Click Compare in the toolbar
- Select the base branch and head branch
- View the diff showing all metric changes
Each change is categorized:
| Severity | Meaning | Examples |
|---|---|---|
| Breaking | Changes that alter query results or remove definitions | Metric removed, expression changed, dimension dropped, dataset source repointed, join keys changed |
| Safe | Additive changes that do not affect existing queries | New metric added, new dimension, new dataset or relationship |
| Info | Cosmetic changes with no query impact | Description updated, label changed, formatting adjustments |
The diff shows before/after values for each change so reviewers can assess impact at a glance. When a PR contains any breaking change, the verdict is Blocked, requiring explicit review before merge.
Metric Gate in Slimmer CI
When Slimmer CI is enabled, the metric diff runs automatically on every pull request. Breaking metric changes block the PR just like a failing build. Results appear in the PR Overview tab and digest comment. See Slimmer CI for details.
A Portable Definition Format
Every definition in the dbdeux Semantic Layer is plain YAML following the Open Semantic Interchange (OSI) metadata model, and it lives in your own repository next to the dbt models it describes.
That has a practical consequence worth being blunt about: your metrics are not locked inside dbdeux. They are reviewable in a pull request, versioned in your Git history, and readable by anything that understands the format. If you ever want to take them somewhere else, you already have them.
Bringing Your Metrics In
Whatever your team has modelled so far, there is an on-ramp. Click Import in the toolbar and pick where your definitions live today. Every path produces the same portable OSI YAML, ready to review and commit.
One rule holds across all of them: nothing is silently dropped. Anything that does not translate cleanly is reported as a warning naming the construct and why it could not be converted, so you always know what still needs a human decision. The result is shown as YAML before anything happens to your project, so an import is never a mystery write into a system you cannot inspect. Copy it out, or let dbdeux place it for you.
Add It to Your Repo
Once you are happy with the converted YAML, Add to repo puts it in your project for you:
- Accept the suggested path (
models/semantic/metrics.osi.yml) or type your own. Any folders that do not exist yet are created along the way - Pick the branch it should land on. Protected branches are shown but cannot be selected, so an import can never touch a branch your team has locked
- If a file already sits at that path, it is left alone unless you explicitly tick the option to replace it
The file arrives as an ordinary uncommitted change on that branch. Open it in the editor, read it, adjust it, then commit and push exactly as you would any other edit. Nothing is written to your repository history on your behalf, so a generated draft still goes through the same review your team applies to everything else.
If you added the file to a different branch than the one you were browsing, the catalog follows it and tells you it has switched, so your new definitions are on screen immediately instead of appearing to have vanished.
Snowflake Semantic Views
If you already model semantics in Snowflake, you can bring those definitions across without rewriting them. Paste your CREATE SEMANTIC VIEW statement and it is converted piece by piece:
| In your semantic view | Becomes |
|---|---|
| Each logical table, with its alias and fully qualified source | A dataset, with its description carried over |
PRIMARY KEY | The dataset's primary key |
RELATIONSHIPS | Joins between datasets |
FACTS | Row-level fields on the dataset |
DIMENSIONS | Dimensions you can group by |
METRICS | Governed metrics, with their references resolved to the right dataset |
Constructs that have no equivalent, such as window-function metrics, private items, and time-based relationship types, are listed as warnings rather than quietly skipped.
dbt Semantic Models
If your dbt project already uses semantic_models in YAML, import them directly:
- Click Import in the toolbar
- Select the dbt tab
- Choose which semantic models to import
- The definitions are converted and added to your catalog
LookML
Import metric definitions from Looker's LookML files:
- Click Import and select the LookML tab
- Paste or upload your LookML file content
- Views and explores are mapped to datasets, dimensions, joins, and metrics
Cube
Import from Cube data model definitions:
- Click Import and select the Cube tab
- Paste or upload your Cube schema
- Measures and dimensions are converted to the catalog format
Start From Nothing: Generate From Your Repo
Most teams do not have a semantic layer yet, and a blank catalog is the hardest place to start. Generate removes that first step entirely: it reads what dbt already knows about your project and drafts a starter model for you.
| What dbt already has | What you get |
|---|---|
| Documented models in your schema YAML | Datasets pointed at those models |
unique and not_null tests | Primary keys |
relationships tests | Joins between datasets |
| Date-like columns | Time dimensions, ready to query by day, week, month, quarter, or year |
| Amount, revenue, quantity, and similar columns | Starter metrics, plus a row-count metric per dataset |
Everything generated is a proposal, and it says so. Each inference is flagged as a warning so you can see precisely which parts were guessed and confirm or correct them before publishing. Nothing is published on your behalf.
If your project has no documentation to work from, you get a plain message telling you to document your models first rather than an empty result you have to interpret.
Validation
The Semantic Layer validates your semantic model definitions and surfaces issues directly in the catalog:
- Errors: Invalid expressions, missing references, duplicate names
- Warnings: Unused dimensions, potential performance issues
- Info: Style suggestions, documentation gaps (e.g., adding
ai_contextfor better Atlas grounding)
Issues appear inline in the catalog sidebar with severity badges so you can fix problems before they reach production.
Atlas AI Grounding
When the Semantic Layer is enabled, the Atlas AI Co-pilot automatically reads your governed metric definitions. This means:
- Atlas answers are grounded in your actual metric names and expressions, read from your published catalog version so a co-pilot answer always matches what the API and your dashboards return
- Questions like "how is revenue calculated?" return your team's governed definition, not a guess
- Atlas also reads governance metadata, so it will tell you a metric is deprecated and point at its replacement rather than steering you toward something you should not use
- Suggested SQL uses your metric layer rather than raw table references
- Up to 40 relevant metrics are included in each AI context window
This bridges the gap between your metric catalog and day-to-day development.
How It Fits Together
The Semantic Layer works alongside the other dbdeux features:
- Data Products: Bundle metrics into governed data products with SLAs, ownership, and maturity tracking
- Share Links: Share your metric catalog externally with tokenized links that require no login
- Slimmer CI: Metric diffs run automatically on PRs to catch breaking metric changes before merge
- Atlas AI: Atlas grounds answers in your governed metric definitions for consistent, accurate responses
- Atlas Catalog: Browse documentation for the models behind your metrics in the Atlas Catalog
- Database Explorer: Browse the underlying warehouse tables that your metrics reference
- Scheduling: Scheduled builds ensure your metric catalog stays in sync with the latest code
How It Compares
| Capability | dbdeux Semantic Layer | dbt Semantic Layer | Looker / LookML | Spreadsheet metrics |
|---|---|---|---|---|
| Definition format | Git-native YAML in your dbt project | dbt Semantic Layer YAML | LookML files | Scattered formulas |
| Live SQL preview | Instant compiled SQL with dialect switching (7 warehouses) | Requires API call | View SQL in Explore | Not available |
| Branch diffs | Side-by-side metric diff with breaking/safe/info severity | Not available | Git diff only | Not available |
| Import | Snowflake Semantic Views, dbt, LookML, and Cube, with every unsupported construct reported rather than dropped | Native only | Native only | Manual migration |
| Starting from scratch | Generate a reviewable starter model from your existing dbt documentation and tests | Write everything by hand | Write everything by hand | Write everything by hand |
| Format ownership | Portable open-standard YAML committed to your own repository | Vendor YAML tied to the platform | Proprietary LookML | Not applicable |
| Ad hoc investigation | Edit and re-run the compiled SQL in place, under the same read-only guarantees | Not available | Explore only | Manual SQL |
| Validation | Inline errors, warnings, and info with file locations | CLI validation | IDE validation | None |
| AI grounding | Metrics are automatically used by Atlas AI for accurate answers | Not available | Not available | Not available |
| AI assistant access | Assistants connect directly and answer from your governed definitions, with per-permission consent and revoke | Not available | Not available | Not available |
| Query execution | Run a metric against your warehouse from the catalog, the API, or an agent | API access only | Requires Looker | Manual SQL |
| Version pinning | Publish an immutable catalog version that every consumer reads from | Not available | Not available | Not available |
| Rollup safety | Metrics declare where they must not be summed, so bad rollups are prevented | Limited | Manual care required | None |
| External sharing | Tokenized share links with no login required | API access only | Requires Looker license | File sharing |
| Authoring | Form Builder, full YAML editor, and AI-drafted changes over the same file, with your comments preserved | Hand-written YAML | LookML code editor | Manual |
| Definition history | Per-file history with view and restore from inside the editor | Git history outside the tool | Git history outside the tool | None |
| Query history | Every query kept, including failed attempts, with its source, SQL, timing, catalog version, and one-click rerun | Not available | Query history per user in the admin panel | None |
| Interfaces | UI, REST API, GraphQL, and an AI agent endpoint over one definition | REST and JDBC | Looker API | None |