Skip to main content

Semantic models

Semantic models are the foundation for data definition in MetricFlow, which powers the dbt Semantic Layer:

  • Think of semantic models as nodes connected by entities in a semantic graph.
  • MetricFlow uses YAML configuration files to create this graph for querying metrics.
  • Each semantic model corresponds to a dbt model in your DAG, requiring a unique YAML configuration for each semantic model.
  • You can create multiple semantic models from a single dbt model (SQL or Python), as long as you give each semantic model a unique name.
  • Configure semantic models in a YAML file within your dbt project directory. Refer to the best practices guide for more info on project structuring.
  • Organize them under a metrics: folder or within project sources as needed.
A semantic model is made up of different components: Entities, Measures, and Dimensions.A semantic model is made up of different components: Entities, Measures, and Dimensions.
📹 Learn about the dbt Semantic Layer with on-demand video courses!

Explore our dbt Semantic Layer on-demand course to learn how to define and query metrics in your dbt project.

Additionally, dive into mini-courses for querying the dbt Semantic Layer in your favorite tools: Tableau, Hex, and Mode.

Here we describe the Semantic model components with examples:

NameChoose a unique name for the semantic model. Avoid using double underscores (__) in the name as they're not supported.Required
DescriptionIncludes important details in the descriptionOptional
ModelSpecifies the dbt model for the semantic model using the ref functionRequired
DefaultsThe defaults for the model, currently only agg_time_dimension is supported.Required
EntitiesUses the columns from entities as join keys and indicate their type as primary, foreign, or unique keys with the type parameterRequired
Primary EntityIf a primary entity exists, this component is Optional. If the semantic model has no primary entity, then this property is required.Optional
DimensionsDifferent ways to group or slice data for a metric, they can be time or categoricalRequired
MeasuresAggregations applied to columns in your data model. They can be the final metric or used as building blocks for more complex metricsOptional
LabelThe display name for your semantic model node, dimension, entity, and/or measuresOptional
configUse the config property to specify configurations for your metric. Supports meta, group, and enabled configs.Optional

Semantic models components

The complete spec for semantic models is below:

- name: the_name_of_the_semantic_model ## Required
description: same as always ## Optional
model: ref('some_model') ## Required
defaults: ## Required
agg_time_dimension: dimension_name ## Required if the model contains measures
entities: ## Required
- see more information in entities
measures: ## Optional
- see more information in the measures section
dimensions: ## Required
- see more information in the dimensions section
primary_entity: >-
if the semantic model has no primary entity, then this property is required. #Optional if a primary entity exists, otherwise Required

You can refer to the best practices guide for more info on project structuring.

The following example displays a complete configuration and detailed descriptions of each field:

- name: transaction # A semantic model with the name Transactions
model: ref('fact_transactions') # References the dbt model named `fact_transactions`
description: "Transaction fact table at the transaction level. This table contains one row per transaction and includes the transaction timestamp."
agg_time_dimension: transaction_date

entities: # Entities included in the table are defined here. MetricFlow will use these columns as join keys.
- name: transaction
type: primary
expr: transaction_id
- name: customer
type: foreign
expr: customer_id

dimensions: # dimensions are qualitative values such as names, dates, or geographical data. They provide context to metrics and allow "metric by group" data slicing.
- name: transaction_date
type: time
time_granularity: day

- name: transaction_location
type: categorical
expr: order_country

measures: # Measures are columns we perform an aggregation over. Measures are inputs to metrics.
- name: transaction_total
description: "The total value of the transaction."
agg: sum

- name: sales
description: "The total sale of the transaction."
agg: sum
expr: transaction_total

- name: median_sales
description: "The median sale of the transaction."
agg: median
expr: transaction_total

- name: customers # Another semantic model called customers.
model: ref('dim_customers')
description: "A customer dimension table."

- name: customer
type: primary
expr: customer_id

- name: first_name
type: categorical


Define the name of the semantic model. You must define a unique name for the semantic model. The semantic graph will use this name to identify the model, and you can update it at any time. Avoid using double underscores (__) in the name as they're not supported.


Includes important details in the description of the semantic model. This description will primarily be used by other configuration contributors. You can use the pipe operator (|) to include multiple lines in the description.


Specify the dbt model for the semantic model using the ref function.


Defaults for the semantic model. Currently only agg_time_dimension. agg_time_dimension represents the default time dimensions for measures. This can be overridden by adding the agg_time_dimension key directly to a measure - see Dimensions for examples.


To specify the entities in your model, use their columns as join keys and indicate their type as primary, foreign, or unique keys with the type parameter.

Primary entity

MetricFlow requires that all dimensions be tied to an entity. This is to guarantee unique dimension names. If your data source doesn't have a primary entity, you need to assign the entity a name using the primary_entity: entity_name key. It doesn't necessarily have to map to a column in that table and assigning the name doesn't affect query generation.

You can define a primary entity using the following configs:

name: bookings_monthly_source
description: bookings_monthly_source
agg_time_dimension: ds
model: ref('bookings_monthly_source')
- name: bookings_monthly
agg: sum
create_metric: true
primary_entity: booking_id

Here are the types of keys:

  • Primary Only one record per row in the table, and it includes every record in the data platform.
  • Unique Only one record per row in the table, but it may have a subset of records in the data platform. Null values may also be present.
  • Foreign Can have zero, one, or multiple instances of the same record. Null values may also be present.
  • Natural A column or combination of columns in a table that uniquely identifies a record based on real-world data. For example, the sales_person_id can serve as a natural key in a sales_person_department dimension table.


Dimensions are different ways to organize or look at data. For example, you might group data by things like region, country, or what job someone has. However, trying to set up a system that covers every possible way to group data can be time-consuming and prone to errors.

Instead of trying to figure out all the possible groupings ahead of time, MetricFlow lets you ask for the data you need and sorts out how to group it dynamically. You tell it what groupings (dimensions parameters) you're interested in by giving it a name (either a column or SQL expression like "country" or "user role") and the type of grouping it is (categorical or time). Categorical groups are for things you can't measure in numbers, while time groups represent dates.

  • Dimensions are identified using the name parameter, just like identifiers.
  • The naming of groups must be unique within a semantic model, but not across semantic models since MetricFlow, uses entities to determine the appropriate groups.
  • MetricFlow requires all dimensions to be tied to a primary entity.

While there's technically no limit to the number of dimensions in a semantic model, it's important to ensure the model remains effective and efficient for its intended purpose.

For time groups

For semantic models with a measure, you must have a primary time group.


Measures are aggregations applied to columns in your data model. They can be used as the foundational building blocks for more complex metrics, or be the final metric itself.

Measures have various parameters which are listed in a table along with their descriptions and types.

nameProvide a name for the measure, which must be unique and can't be repeated across all semantic models in your dbt project.Required
descriptionDescribes the calculated measure.Optional
aggdbt supports the following aggregations: sum, max, min, avg, median, count_distinct, percentile, and sum_boolean.Required
exprEither reference an existing column in the table or use a SQL expression to create or derive a new one.Optional
non_additive_dimensionNon-additive dimensions can be specified for measures that cannot be aggregated over certain dimensions, such as bank account balances, to avoid producing incorrect results.Optional
agg_paramsSpecific aggregation properties, such as a percentile.Optional
agg_time_dimensionThe time field. Defaults to the default agg time dimension for the semantic model.Optional
labelString that defines the display value in downstream tools. Accepts plain text, spaces, and quotes (such as orders_total or "orders_total"). Available in dbt version 1.7 or higher.Optional
create_metricCreate a simple metric from a measure by setting create_metric: True. The label and description attributes will be automatically propagated to the created metric. Available in dbt version 1.7 or higher.Optional


Metric nodes will reflect dependencies on semantic models based on their measures. However, dependencies based on filters should not be reflected in:

This is because metrics need to source nodes for their depends_on attribute from a few different places:

  • RATIO and DERIVED type metrics should reference Metric.type_params.input_metrics.
  • SIMPLE type metrics should reference Metric.type_params.measure.

For example, when you run the command dbt list --select my_semantic_model+, it will show you the metrics that belong to the specified semantic model.

But there's a condition: Only the metrics that actually use measures or derived metrics from that semantic model will be included in the list. In other words, if a metric only uses a dimension from the semantic model in its filters, it won't be considered as part of that semantic model.