dbt Semantic Layer: what it is and who needs one

By Arshad Ansari

Ask four people what revenue was last month and you can get four numbers. Nobody is lying. The definition just lives in four places: one dashboard excludes refunds, one includes them, one filters to completed orders, and one was written by someone who left eighteen months ago. It is almost never found on purpose — it surfaces in a meeting where two people are reading from two screens.

A semantic layer is the attempt to fix that by moving the definition somewhere everything else has to ask. The dbt Semantic Layer does it by putting the metric in your dbt project as YAML and compiling it to SQL on demand, so the number is generated the same way no matter who asked.

I build data platforms on my own — Dagster orchestrating the pipelines, ClickHouse serving the results — so my interest in this is practical rather than theoretical. Is the benefit real at a small size, and how much of it can you have without a licence? Both answers turned out to be more interesting than the marketing.

The short answer

Skip it if one BI tool serves all your reporting. A mart table called fct_orders_daily with a column called net_revenue, a test on it and a description in the YAML gives you the same single definition with far less machinery. The metric is a column, the governance is code review, and there is nothing new to run.

Adopt it when the same number is being rebuilt in more than one place — a second BI tool, embedded analytics inside your product, analysts pulling into spreadsheets and notebooks, or an AI agent writing its own SQL. At that point the definition is being copied, and copies drift.

Define metrics under dbt Core either way if you are curious. That part is free and portable. What you pay for is serving them.

What it actually is

Three pieces, and the names matter because the docs changed them recently.

A semantic model sits on top of a dbt model and describes it: its entities (the join keys — dbt's docs call them "the traversal paths, or edges between semantic models"), its dimensions (the ways you group and slice: time, status, country), and its metrics.

MetricFlow is the engine. The dbt docs describe it as "a SQL query generation tool designed to streamline metric creation across different data dimensions". Give it a metric and a set of dimensions and it builds a graph — semantic models as nodes, entity join paths as edges — and works out the query. The docs claim it "chooses the appropriate join type and avoids fan-out or chasm joins", which is the part that would otherwise be a human getting a GROUP BY wrong.

Metrics come in five types as of September 2026: simple, ratio, cumulative, derived and conversion. Simple aggregates a column. Ratio divides one metric by another. Derived is arithmetic over other metrics. Cumulative accumulates over a window. Conversion measures one event following another within a window.

The important structural point: a metric is not a table. Nothing is pre-aggregated. The definition becomes a query when something asks, which is why the same metric can be sliced by a dimension nobody anticipated without anyone building a new model.

What it looks like

The YAML spec moved in dbt v1.12. Semantic models used to be a top-level semantic_models: key with a separate measures: list; now they are nested inside the model's own YAML entry, entities and dimensions are declared on columns, and measures are gone — replaced by simple metrics. This is today's shape, for dbt v1.12 and later:

# models/marts/_fct_orders.yml — dbt v1.12 and later
models:
  - name: fct_orders
    description: "One row per order."
    semantic_model:
      enabled: true

    agg_time_dimension: ordered_at

    columns:
      - name: order_id
        entity:
          type: primary
          name: order

      - name: customer_id
        entity:
          type: foreign
          name: customer

      - name: ordered_at
        granularity: day
        dimension:
          type: time

      - name: order_status
        dimension:
          type: categorical
          name: status

    metrics:
      - name: revenue
        description: "Net order value, completed orders only."
        type: simple
        label: Revenue
        agg: sum
        expr: net_amount
        filter: "{{ Dimension('order__status') }} = 'completed'"

      - name: order_count
        description: "Completed orders."
        type: simple
        label: Orders
        agg: count_distinct
        expr: order_id
        filter: "{{ Dimension('order__status') }} = 'completed'"

      - name: average_order_value
        description: "Revenue divided by completed orders."
        type: ratio
        label: Average order value
        numerator: revenue
        denominator: order_count

Two things to notice. The filter on revenue is the argument for the whole idea: "completed orders only" is written once, and anything asking for revenue gets it. And average_order_value is defined in terms of the other two metrics rather than re-deriving them, so a change to what "completed" means propagates instead of needing to be found in five dashboards.

If you have semantic models on the old spec, dbt ships a migration command, dbt-autofix deprecations --semantic-layer, and documents the before-and-after on its migrate to the latest YAML spec page. Check that page rather than copying an older blog post: the pre-1.12 syntax is still all over the internet.

What is free and what is paid

This is the part most explainers get vague about, so here it is plainly, checked in September 2026.

dbt Core, localdbt platform (paid)
Define semantic models and metrics in YAMLYesYes
Validate themYes — mf validate-configsYes — dbt sl validate
Compile to SQL and queryYes — mf query, from your machineYes
JDBC / ADBC / GraphQL / Python SDKNoStarter and above
BI tool integrationsNoStarter and above
Exports and result cachingNoEnterprise tiers for governed metrics with caching

MetricFlow itself is open source under the Apache 2.0 licence, and compatible with dbt 1.6 and higher. Install it with pip install dbt-metricflow, or pip install "dbt-metricflow[dbt-snowflake]" to pull an adapter with it. Then mf list metrics, mf query --metrics revenue --group-by order__status, mf validate-configs.

dbt's own FAQ puts the boundary this way: dbt users "can use MetricFlow features, like defining metrics in their projects, without a dbt platform plan" and "can also query their semantic layer locally using the command line. However, they won't be able to use the APIs or available integrations to access metrics dynamically."

On price, the dbt pricing page at the time of writing lists Starter at $100 per user per month with five developer seats and 5,000 queried metrics per month, and Enterprise and Enterprise+ at custom prices with 20,000 queried metrics per month. The free Developer plan does not include the Semantic Layer. Note that "queried metrics per month" is a usage meter, not a seat count — a dashboard that refreshes every fifteen minutes spends it faster than a person does. I went through the rest of that pricing structure in dbt Core vs dbt Cloud.

Where it runs

Supported data platforms, per the docs today: Snowflake, BigQuery, Databricks, Redshift, Postgres and Trino. The FAQ adds that "support for other data platforms, such as Fabric, isn't available at this time."

That list matters to me, because ClickHouse and DuckDB are not on it. My own production analytical store is ClickHouse, and much of what I build sits on DuckDB — so for my stack the dbt Semantic Layer is not currently an option, hosted or local. If you are outside those six, check before you plan around it, and check again in six months: that list is the kind of thing that grows.

On the consumption side, the integrations page today lists Power BI, Tableau, Google Sheets, Microsoft Excel, Omni, Dot, Hex, Klipfolio PowerMetrics, Mode, Push.ai, Sigma (in preview) and Steep, plus anything that can use a generic JDBC driver or the Arrow Flight SQL JDBC driver at version 12.0.0 or higher.

Do you actually need one?

Here is the honest version, and it is not what a vendor page will tell you.

A semantic layer is a governance tool, and governance is only worth its cost when there are several parties to govern. If your company has one BI tool and three people who write SQL, the same discipline is available for free: build the metric as a column in a mart table, name it precisely, test it, document it in the model YAML, and make everything read that table. The definition is in one place, it is in version control, it changes through pull requests, and nobody has to learn a query API. Metrics as models works, and it works for longer than people expect.

What it cannot do is serve a metric in combinations you did not pre-build. fct_orders_daily gives you revenue by day. Revenue by customer segment and channel and day means another model, or a BI tool doing its own aggregation — and that second path is exactly where the definitions start to diverge, because the aggregation logic has now left dbt.

So the question is not how big you are. It is how many independent things need the same number. The signals that mart tables have run out:

  • More than one BI tool, or a BI tool plus embedded analytics inside a product you ship.
  • Analysts who pull into spreadsheets and notebooks and re-aggregate there. This is the quiet one, and it is nearly universal.
  • A metric whose definition changes more than once a year — pricing, refunds, what counts as an active customer. Every change is a search-and-replace across every place it was implemented.
  • Two teams who have each built their own version of the same table, and neither knows.
  • An LLM or agent generating queries against your warehouse.

The case I find most interesting: metrics for agents

That last bullet deserves its own section, because it is the strongest argument for a semantic layer right now and it barely existed two years ago.

When you point a language model at raw tables, it has to infer meaning from column names. It will infer plausibly and it will sometimes infer wrongly, and a wrong number delivered fluently is worse than an error, because nobody checks it. I wrote about the mechanics of doing this locally in asking your database questions in plain English, and about the safety patterns in connecting an LLM to your database without losing control. The pattern I rated highest in that second post — the model never writes SQL, it picks from a menu of definitions a human wrote — is exactly what a semantic layer is.

The difference is in what the model is allowed to get wrong. Given raw tables, it can choose the wrong join grain, forget a status filter, double-count through a fan-out, and hand you a number that looks fine. Given metrics and dimensions, its job is to pick revenue grouped by order__status for a date range, and the joins and filters are MetricFlow's problem, decided in advance by a person. The failure mode shrinks from "invented a number" to "picked the wrong metric", which a human can see.

dbt has built for this directly: its MCP server exposes Semantic Layer tools to AI clients, in a self-hosted flavour for local projects and a remote one for consumption, with the Semantic Layer parts needing a platform plan. And the industry is standardising the format. Apache Ossie — the renamed Open Semantic Interchange, launched by Snowflake with Salesforce, dbt Labs and others in September 2025 and accepted into the Apache Incubator in July 2026 — is a vendor-neutral spec for expressing metrics, dimensions and their relationships so they move between tools. dbt's docs already list Ossie documents as an alternative to its native YAML. dbt Labs open-sourced MetricFlow under Apache 2.0 as part of the same push.

If you are planning to put an agent anywhere near your numbers, the governed-definition question is the one to settle first, before the model choice. The AI workflow teardown is the checklist I use for that — it asks who can stop it, what happens when it is wrong, and what it is allowed to see.

The alternatives, briefly

Cube is the main standalone semantic layer: define metrics, dimensions, joins and access rules once, serve them over SQL, REST and GraphQL to BI tools and AI agents. Its backend is Apache 2.0 licensed. LookML has done this inside Looker for years, and is the reason many people already know what a semantic layer is. Snowflake semantic views and Databricks Unity Catalog metric views are the warehouse-native versions, each wired into that vendor's AI assistant — if you are entirely on one platform, look at its own before you buy a layer on top. Lightdash reads metrics out of your dbt project directly and gives analysts a governed exploration surface. Malloy is a different approach again: a query language built around reusable analytical logic rather than a layer over SQL. And the alternative to weigh first is still no semantic layer — a small set of well-named, well-tested mart tables, which is what most teams should price against everything above.

Where I'd start

Define the metrics in dbt Core and query them with mf before you pay anything. It costs an afternoon, it tells you whether your models are actually shaped for it (they often are not — a semantic model wants a clean grain and honest entity columns), and the YAML is portable if you later move to the hosted APIs or to Ossie. That exercise also forces the conversation the whole thing is really about: getting three people to agree, in writing, on what revenue means. If your team is writing dbt models with an AI assistant, this is worth doing by hand — a metric definition is a business decision, not a code-generation task, and I made the case for reviewing generated dbt work carefully in letting Claude Code write your dbt models.

A semantic layer does not create agreement. It records agreement, and then refuses to let it drift. If nobody has had the argument yet, the tool will not have it for you.

For the wider question of whether your models and tests are in shape before you add anything on top, the data platform teardown is the checklist — free, no email. If you want someone who runs this kind of platform in production to look at your dbt project and say plainly whether metrics-as-models is still enough, that is the kind of thing I do. The scoping call below is free.

Common questions

What is the dbt Semantic Layer?
It is a way to define business metrics once, in YAML, inside your dbt project, and have them compiled into SQL when something asks for a number. You describe a model as a semantic model — its entities (join keys), its dimensions (the ways you slice) and its metrics — and MetricFlow works out the joins and generates the query. The metric is not a stored table. It is a definition that becomes a query at request time, so a dashboard, a spreadsheet and an AI agent all get the same answer from the same source.
Is the dbt Semantic Layer free?
Partly. MetricFlow, the engine underneath it, is open source under the Apache 2.0 licence, and dbt's own FAQ says dbt users "can use MetricFlow features, like defining metrics in their projects, without a dbt platform plan" and can query those metrics locally from the command line. What costs money is serving them to other tools. At the time of writing (September 2026) dbt's docs say you must be on a Starter or Enterprise-tier account to query metrics through the Semantic Layer APIs and integrations, and the pricing page lists Starter at $100 per user per month with 5,000 queried metrics per month.
Does the dbt Semantic Layer work with dbt Core?
Yes for defining and validating metrics, no for serving them. Install `dbt-metricflow` with pip and you get the `mf` commands — `mf list metrics`, `mf query`, `mf validate-configs`, `mf health-checks` — which compile your metrics to SQL and run them against your warehouse from your own machine. The dbt docs are explicit that dbt Core users "won't be able to use the APIs or available integrations to access metrics dynamically". So the definitions are portable and free; the JDBC, ADBC, GraphQL and Python SDK endpoints that BI tools connect to are the paid part. Checked September 2026.
What is MetricFlow?
MetricFlow is the SQL generation engine that powers the dbt Semantic Layer. dbt's docs describe it as "a SQL query generation tool designed to streamline metric creation across different data dimensions". It reads your semantic models and metrics from YAML, builds a graph where semantic models are nodes and entity join paths are edges, and works out the right joins for whatever combination of metric and dimension you asked for — the docs say it "chooses the appropriate join type and avoids fan-out or chasm joins". It is Apache 2.0 licensed and compatible with dbt version 1.6 and higher.
Which BI tools work with the dbt Semantic Layer?
As of September 2026 dbt's available integrations page lists first-class support for Power BI, Tableau, Google Sheets, Microsoft Excel, Omni, Dot, Hex, Klipfolio PowerMetrics, Mode, Push.ai, Sigma (in preview) and Steep. Beyond that list, any tool with a generic JDBC driver option, or one compatible with the Arrow Flight SQL JDBC driver version 12.0.0 or higher, can connect. There are also GraphQL and Python SDK options for custom integrations. All of these go through the hosted APIs, so they need a paid dbt platform plan.
Do I need a semantic layer?
Only if several different things need the same number. If one BI tool serves all your reporting, well-named and well-tested mart tables in dbt do the same job with less machinery — the metric is a column, the governance is code review, and everyone reads the same table. A semantic layer starts to earn its place when the same definition is being re-implemented in more than one place: two or more BI tools, embedded analytics in a product, analysts pulling into spreadsheets and notebooks, or LLM agents writing their own queries. The test is not company size. It is how many independent consumers of the same metric you have.
What are the alternatives to the dbt Semantic Layer?
Cube is the main standalone one — an open-source semantic layer (its backend is Apache 2.0 licensed) that exposes metrics over SQL, REST and GraphQL to BI tools and AI agents. Looker's LookML has done this inside Looker for years. Your warehouse may have its own: Snowflake has semantic views and Databricks has Unity Catalog metric views, both feeding their respective AI assistants. Lightdash reads metrics straight out of your dbt project. Malloy is a different query language built around reusable analytical logic. And the option most teams should price first is no semantic layer at all — a small set of governed mart tables.
Is a semantic layer useful for AI and LLM agents?
This is its strongest current argument. An LLM pointed at raw tables has to guess what "revenue" means, and it will guess plausibly and wrongly. A semantic layer turns the task from writing arbitrary SQL into picking a metric and some dimensions from a list a human wrote, which is both safer and easier to audit. dbt ships an MCP server that exposes Semantic Layer tools to AI clients, and the Apache Ossie specification — the renamed Open Semantic Interchange, accepted into the Apache Incubator in July 2026 — exists largely to make these definitions portable between tools and AI applications.

Get new posts by email

Data engineering notes like this one — pipelines, warehouse cost, and what actually breaks in production. A few a month, never padded to hit a schedule.

No sequence, no pitch deck. Reply 'stop' once and you're off — it reaches me, not a queue.

Want the whole playbook?

If this was useful, the long version is my book. Local-First Analytics — 314 pages, runnable code for every chapter — is the full build: DuckDB, Parquet and Arrow, from install to production. On Amazon, or request a free review copy.

Get the book

Not ready to buy? Read chapter 1 free — the whole chapter, no email required.

Rather talk it through? Book a free 30-minute call. No slot that suits your time zone? Email [email protected].