Semantic layers
One shared, code-defined model of metrics, dimensions and joins that BI tools, apps and AI agents query by name, which the layer compiles to SQL against the warehouse and often caches.
2 technologies on this page ↓How it works
Without one, every dashboard, notebook and app writes its own SQL for “revenue”, and they drift apart: one subtracts refunds, another doesn’t. A semantic layer moves those definitions into one model, usually YAML or a small language in git. The model names entities (orders, customers), the joins between them, dimensions to group and filter by (country, month, status) and measures or metrics with their aggregation (net_revenue = SUM(amount) - SUM(refunded)). Consumers ask for metrics by dimensions through the layer’s API: a SQL interface that looks like a database, REST or GraphQL for apps, or an MCP server for AI agents. The layer checks the request against the model, applies access rules such as row-level filters for the caller, works out the joins, and generates SQL in the warehouse’s own dialect. Many layers also cache: results in memory, or rollup tables refreshed ahead of time and used whenever a query matches them, so busy dashboards don’t rescan raw tables. The warehouse still does the heavy work; the layer decides what to ask it.
A restaurant chain’s recipe book. Every branch, the delivery app and the catering team order “house curry” by name, and the kitchen cooks it the same way each time. Nobody improvises their own version, and when the recipe changes, it changes everywhere at once.
Reach for it when
- Several tools (BI, spreadsheets, embedded dashboards, AI agents) report the same metrics and the numbers disagree
- Customer-facing analytics, where an app needs a governed API with per-tenant access rules instead of raw SQL
- AI agents should answer questions from defined metrics instead of guessing at raw tables
- Dashboards repeatedly hit the warehouse with the same aggregations and you want a cache in front of it
Think twice when
- One team, one BI tool and a handful of reports: the BI tool’s own model or a few dbt models is enough
- Exploratory analysis over new, unmodelled data, where analysts need raw SQL more than governed metrics
- You can’t staff the model: an outdated semantic layer is a second source of wrong numbers
A real example
A SaaS company reports “active customers” and “net revenue” in its BI tool, in a customer-facing usage dashboard and through an AI chat assistant. Before, each had its own SQL, and the board deck and the app disagreed by 4% because one forgot refunds. With a semantic layer, the definition lives in one YAML file reviewed in pull requests. The BI tool connects to its SQL endpoint, the app calls its REST API with a token that limits each customer to their own rows, and the assistant uses its MCP server. A monthly rollup of revenue by plan and country answers 90% of dashboard queries in milliseconds without touching the warehouse.
Technologies
Specific products, and what each does differently.
What each provider calls it
- AWS
- Amazon Quick Sight Topics
- Google Cloud
- Looker (LookML)
- Azure
- Power BI semantic models
- Open source & others
- Cube, dbt Semantic Layer (MetricFlow, Apache 2.0), Snowflake semantic views, Apache Ossie (exchange format)
Where the model lives#
Most semantic layers do the same job; they differ in who owns the model and who can query it.
Inside a BI tool
Looker, Power BILookML models in a Git-backed Looker project describe dimensions, measures and joins, and Looker’s SQL generator turns each Explore query into SQL. Power BI semantic models are, in effect, Analysis Services tabular models. Both are built for their own tool first.
Standalone and headless
CubeCube Core keeps cubes and views in YAML or JavaScript and exposes them through a Postgres-compatible SQL API, REST and GraphQL, with pre-aggregations as its cache. It has no UI of its own, so any BI tool, app or agent can sit on top.
Next to the transformations
dbtThe dbt Semantic Layer defines metrics in the dbt project, on top of the models that build the tables. MetricFlow compiles requests into a query plan and then into SQL for the target engine; it moved to the Apache 2.0 licence in 2025. The hosted Semantic Layer needs a dbt Starter or Enterprise-tier account.
Inside the warehouse
SnowflakeSnowflake semantic views are schema-level objects created with CREATE SEMANTIC VIEW. You query them with SELECT, share them through listings and give them to Cortex Agents, but only inside Snowflake.
In code · python
import sqlite3
# The semantic layer: metrics, dimensions and joins, defined once
MODEL = {
"table": "orders o",
"joins": {"customers": "JOIN customers c ON c.id = o.customer_id"},
"metrics": {"revenue": "SUM(o.amount)", "orders": "COUNT(*)",
"net_revenue": "SUM(o.amount) - SUM(o.refunded)"},
"dimensions": {"country": ("c.country", "customers"), "status": ("o.status", None)},
}
def compile_query(metrics: list[str], by: list[str]) -> str:
dims = [MODEL["dimensions"][d] for d in by]
joins = sorted({MODEL["joins"][j] for _, j in dims if j})
cols = [f"{expr} AS {d}" for d, (expr, _) in zip(by, dims)]
cols += [f"{MODEL['metrics'][m]} AS {m}" for m in metrics]
sql = f"SELECT {', '.join(cols)} FROM {MODEL['table']} {' '.join(joins)}"
return sql + (f" GROUP BY {', '.join(e for e, _ in dims)}" if dims else "")
db = sqlite3.connect(":memory:")
db.executescript("""
CREATE TABLE customers (id INT, country TEXT);
CREATE TABLE orders (id INT, customer_id INT, amount REAL, refunded REAL, status TEXT);
INSERT INTO customers VALUES (1, 'DE'), (2, 'FR');
INSERT INTO orders VALUES (1, 1, 100, 0, 'paid'), (2, 1, 50, 50, 'refunded'), (3, 2, 80, 0, 'paid');
""")
# A BI tool, an app and an AI agent all ask by name; nobody rewrites the SQL
sql = compile_query(["net_revenue"], by=["country"])
print(sql)
# SELECT c.country AS country, SUM(o.amount) - SUM(o.refunded) AS net_revenue FROM orders o JOIN customers c ON c.id = o.customer_id GROUP BY c.country
print(db.execute(sql).fetchall()) # [('DE', 100.0), ('FR', 80.0)]Often confused with
Where it came from1991–2025
The idea dates to the start of business intelligence. In November 1991 Business Objects filed a US patent, granted in 1996, for a system that let end users query relational databases “without knowing the relational structure” or SQL: users worked with familiar business terms, called business objects, and the software wrote the queries. Rivals such as Cognos paid licence fees for it, and for decades each BI tool kept its own model that only it could use.
Looker made the model code. LookML describes dimensions, measures and joins in files kept in Git, and Looker generates SQL from it for every query; Google completed its acquisition of Looker in February 2020. In the late 2010s and early 2020s, standalone products split the model from the dashboard entirely, under names like “metrics layer”, “headless BI” or “universal semantic layer”. Cube.js, released as open source in 2019 from the engine behind the Statsbot BI app, served one model to any front end. dbt Labs said in 2021 that it would build its own semantic layer, and in 2023 bought Transform, whose MetricFlow engine compiles metric definitions into SQL.
Large language models raised the stakes: an agent writing SQL against raw tables invents its own definitions. In September 2025 Snowflake, RelationalAI and other partners announced the Open Semantic Interchange, an open-source effort to define a common, vendor-agnostic specification for semantic models. That autumn dbt Labs moved MetricFlow to the Apache 2.0 licence, aligned with the same goals and built with partners including Snowflake and Salesforce. The format is now an Apache Incubator project, Apache Ossie, and Cube converts models to and from it.
Why it’s built this way
- Business terms in front of SQL
- The 1991 patent’s premise: people who know the business shouldn’t need to know table structures or SQL to ask a question, so the system maps their vocabulary onto the database.
- Models as code in version control
- LookML, Cube and dbt all keep definitions in files, so metric changes get review, history, tests and CI like application code, and AI tools can edit them through the same pull requests.
- Compile, don’t copy
- The layer generates SQL for the warehouse’s own dialect instead of storing another copy of the data, so the warehouse stays the single store and the model stays small.
- Headless, with many APIs
- A model locked inside one BI tool can’t serve apps, spreadsheets or agents. Standalone layers expose SQL, REST, GraphQL and MCP so every consumer gets the same numbers.
Timeline
- 1991
Business Objects files its patent for querying databases through business objects (granted 1996)
- 2019
Cube.js released as open source
- 2020
Google completes its acquisition of Looker
- 2023
dbt Labs acquires Transform and its MetricFlow engine
- 2025
Open Semantic Interchange announced in September; MetricFlow moves to Apache 2.0
- Google Patents: US5555403A, Relational database access system using semantically dynamic objects (Business Objects, filed 1991)
- Wikipedia: Semantic layer (history, standalone semantic layers)
- Looker docs: What is LookML?
- Google Cloud blog: Welcoming Looker to Google Cloud (Feb 2020)
- Pulse 2.0: interview with Cube CEO Artyom Keydunov (Statsbot, Cube Core launch in 2019)
- dbt Labs blog: dbt Labs signs definitive agreement to acquire Transform (Feb 2023)
- dbt Labs blog: Announcing open source MetricFlow (Coalesce 2025; 2021 semantic layer plans)
- RelationalAI: RelationalAI joins Snowflake and industry leaders to establish the Open Semantic Interchange (Sept 2025)
- Apache Ossie (incubating): project site
- Cube docs: Apache Ossie (convert Cube models to and from the format)
Sources11
- Cube docs: Introduction (data modeling, access control, caching, APIs)
- Cube docs: Pre-aggregations overview (in-memory cache and rollups)
- GitHub: cube-js/cube README (Cube Core, headless, SQL, REST and GraphQL APIs)
- dbt docs: dbt Semantic Layer (MetricFlow, caching, MCP server, plan requirements)
- GitHub: dbt-labs/metricflow README (query plan to SQL, licence history)
- Looker docs: What is LookML?
- Microsoft Learn: Semantic models in the Power BI service
- Snowflake docs: Overview of semantic views
- Amazon Quick docs: Working with Amazon Quick Sight Topics (multi-dataset semantic layer)
- Cube docs: Apache Ossie (Open Semantic Interchange format)
- Wikipedia: Semantic layer