Skip to main content

lag_tolerance

dbt_project.yml
models:
<resource-path>:
+state:
lag_tolerance: <duration_string>

Definition

Source systems may update more frequently than downstream models need to rebuild. For example, a model used for daily reporting doesn't need to refresh more than once per day, even if new upstream data is available hourly.

With lag_tolerance, you can prevent those unnecessary rebuilds. When dbt State evaluates whether to rebuild a node, it checks whether upstream parents have fresh data that exceeds the lag_tolerance threshold. If they haven't, dbt reuses the existing node rather than cloning or rebuilding it.

This config accepts two value types:

  • Duration strings in the format <number><unit>:

    UnitAccepted values
    Secondss, second, seconds
    Minutesm, minute, minutes
    Hoursh, hour, hours
    Daysd, day, days
    Weeksw, week, weeks
  • Jinja expressions - lag_tolerance is evaluated as a Jinja template, so you can use any dbt context variables (target, var(), env_var()) to set dynamic tolerances. This is useful for applying different tolerances per environment without duplicating config blocks:

    lag_tolerance: "{{ '4h' if target.name == 'prod' else '7d' }}"

When does lag_tolerance apply

lag_tolerance only applies to data freshness checks. A downstream model still rebuilds within its tolerance window if an upstream model's compiled SQL has changed since the last run, regardless of the lag_tolerance setting.

This often happens with incremental models. The first time an incremental model runs, it executes a full load with no WHERE clause. On subsequent runs, is_incremental() becomes true and a filter is appended, changing the compiled SQL. dbt State detects this as a query change on the upstream model and rebuilds all downstream models, even those whose lag_tolerance has not elapsed.

For example, fct_orders is an incremental model that agg_orders_daily depends on:

models/fct_orders.sql
{{ config(materialized='incremental', unique_key='id') }}

select id, amount from {{ ref('raw_orders') }}
{% if is_incremental() %}
where id > (select max(id) from {{ this }})
{% endif %}
models/agg_orders_daily.sql
{{ config(materialized='table', state={'lag_tolerance': '3h'}) }}

select date_trunc('day', created_at) as day, sum(amount) as total
from {{ ref('fct_orders') }}
group by 1

When fct_orders transitions from a full load to an incremental run, its compiled SQL changes. agg_orders_daily rebuilds on that run despite its 3-hour lag_tolerance.

Default

45m. When lag_tolerance is not set, dbt State applies a default tolerance of 45 minutes.

Examples

Use different tolerances per environment

Use a Jinja expression to set a tight tolerance in production and a looser one everywhere else. This keeps production data fresh while reducing unnecessary rebuilds during development:

dbt_project.yml
models:
+state:
lag_tolerance: "{{ '4h' if target.name == 'prod' else '7d' }}"

In this example, models in the prod target rebuild only when upstream data is more than 4 hours old. In all other environments, models wait 7 days before rebuilding.

Apply different tolerances per folder

Set different tolerances for different parts of your project by targeting folders:

dbt_project.yml
models:
<your_project>:
marts:
+state:
lag_tolerance: 1d
staging:
+state:
lag_tolerance: 1h

Override for a specific model

Override the project-level default for a single model:

models/my_model.yml
models:
- name: my_model
config:
state:
lag_tolerance: 1h

Was this page helpful?

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

0
Loading