Defining pre-aggregates
Pre-aggregates are defined under thepre_aggregates key in your model configuration.
If you’re using Lightdash YAML instead of dbt model YAML, see the Lightdash YAML syntax guide for the surrounding model structure.
- dbt v1.9 and earlier
- dbt v1.10+ and Fusion
- Lightdash YAML
Configuration reference
If you specify
time_dimension, you must also specify granularity, and vice versa.Filtered pre-aggregates
Usefilters when you want a pre-aggregate to materialize only a subset of the source data.
For example, this pre-aggregate only stores data for the last 52 weeks:
- dbt v1.9 and earlier
- dbt v1.10+ and Fusion
- Lightdash YAML
How query matching works with filters
Filtered pre-aggregates are only used when the query filters are compatible with the pre-aggregate definition:- A query with the same or narrower filter can use the pre-aggregate
- A query without the filter, or with a broader or incompatible filter, falls back to another pre-aggregate or the warehouse
order_date inThePast 12 weekscan use the pre-aggregateorder_date inThePast 52 weekscan use the pre-aggregateorder_date inThePast 104 weekscannot use the pre-aggregate- no
order_datefilter: cannot use the pre-aggregate
Multiple pre-aggregates per model
You can define multiple pre-aggregates on the same model, each targeting different query patterns. It is better to have multiple small, focused pre-aggregates rather than a single one containing all metrics and dimensions. Including too many dimensions increases the number of unique combinations, which generates large materialization files — this defeats the purpose of pre-aggregates, since they are meant to be smaller and faster than querying the warehouse directly. For example, you might want a fine-grained daily pre-aggregate for detailed dashboards and a coarser monthly one for summary views:Scheduling refreshes
By default, pre-aggregates are materialized when your dbt project compiles. You can also schedule automatic refreshes using cron expressions, using your project’s configured timezone (defaults to UTC):Materialization triggers
Pre-aggregates can be materialized through four different triggers:Row limits
You can setmax_rows to cap the size of a materialization. If the aggregation produces more rows than the limit, the result is truncated.
Materialization role
materialization_role is useful when access to the model depends on required_attributes or any_attributes.
For example, if a joined table is only available to users with region_access: emea, then materializing a pre-aggregate without a fixed access context could produce different results depending on who triggered the build.
Use materialization_role to make materialization run with a stable set of user attributes.
This is intended for access control fields such as:
- dbt v1.9 and earlier
- dbt v1.10+ and Fusion
Complete example
Here’s a full model definition with a pre-aggregate, including joins, scheduling, and row limits:- dbt v1.9 and earlier
- dbt v1.10+ and Fusion
- Lightdash YAML
- Total order amount by status, grouped by day, week, month, or year
- Average order size by status, grouped by month
- Total order amount filtered to completed orders
- Order amount by customer country, grouped by quarter
- Queries including
count_distinctmetrics - Queries grouped by a dimension not in the pre-aggregate (for example,
customer_id) - Queries with hourly granularity (finer than the pre-aggregate’s
day) - Queries without
status = completedor with a broaderstatusfilter - Queries with Parameters, user attributes inside SQL, or
sql_filter - Queries with raw SQL table calculations