Skip to main content

Migrating from state-aware orchestration to dbt State Preview

dbt State improves upon state-aware orchestration in a few key ways:

  • Works everywhere — dbt State works with dbt Core, Fusion, and dbt platform, as well as external orchestrators, across both development and deployment environments.
  • Smarter data freshness tracking — dbt State tracks data freshness across the DAG and automatically propagates it through models materialized as views. Unlike state-aware orchestration's build_after config which compares against the model's last successful execution, dbt State's lag_tolerance compares against the freshness of the underlying data.
  • Advanced change detection — dbt State can detect and ignore file modifications that don't change actual transformation logic, such as adding a comment or cleaning up whitespace.

If you were using state-aware orchestration prior to June 1, 2026, you can continue using it. Your dbt State trial will be extended until the billing period begins on September 1, 2026. If your trial wasn't extended, contact your account team. For details on billing after the trial ends, refer to dbt State usage and pricing.

While dbt State is in preview, there is no required migration timeline — dbt Labs will communicate a timeline when dbt State reaches general availability.

Migrating your configuration

Much of dbt State's configuration will feel familiar if you've used state-aware orchestration, but there is one significant difference: the build_after configs have moved out of the freshness block and into a new state block.

To migrate to dbt State, move your configs from freshness.build_after to the new state block. Refer to the following table for the full mapping.

State-aware orchestrationdbt StateNotes
freshness.build_after.updates_onstate.require_fresh_data_fromSame any and all options with the same behavior:
- any (default): rebuilds when any direct parent has fresh data
- all: rebuilds only when all direct parents have fresh data
freshness.build_after.count + freshness.build_after.periodstate.lag_toleranceCombined into a single field with shorthand values (for example, 1800s, 30m, 12h, 1d, 2w) or Jinja expressions
Loading table...
Backward compatibility in Fusion

In the dbt Fusion engine, dbt State will automatically fall back to your existing build_after configs if lag_tolerance and require_fresh_data_from are not set. This means you can enable dbt State without updating your project configs first.

Examples

You can set these configs at the project level in dbt_project.yml or at the model level in a .yml file.

Project-level:

Before (state-aware orchestration)

dbt_project.yml
models:
+freshness:
build_after:
count: 1
period: day
updates_on: any

After (dbt State)

dbt_project.yml
models:
+state:
lag_tolerance: 1d
require_fresh_data_from: any

Model-level:

Before (state-aware orchestration)

models/my_model.yml
models:
- name: my_model
config:
freshness:
build_after:
count: 1
period: day
updates_on: any

After (dbt State)

models/my_model.yml
models:
- name: my_model
config:
state:
lag_tolerance: 1d
require_fresh_data_from: any

Testing the migration

You can run both configs side by side while validating. State-aware orchestration reads freshness.build_after and dbt State reads the state block, so they won't interfere with each other. Once you're confident everything looks right, remove the build_after configs.

dbt_project.yml
models:
+freshness:
build_after: # state-aware orchestration (remove once migrated)
count: 1
period: day
updates_on: any
+state: # dbt State
lag_tolerance: 1d
require_fresh_data_from: any

Known differences from state-aware orchestration

State-aware orchestration and dbt State differ in a few ways:

  • More models rebuilding than expected: If you notice more rebuilds after you migrate, the most common causes are:

    • Views with select *: dbt State can't determine which columns select * resolves to without querying the upstream schema, so it always rebuilds these views rather than risk reusing a stale result.
    • Non-determinism in Jinja-templated SQL: Macros like dbt_utils.get_relations_by_pattern with dbt_utils.union_relations can return relations in a different order on each run, which produces different compiled SQL. dbt State detects a new hash and rebuilds the model. If that model has downstream dependencies, those models rebuild, too.

    Refer to Why is my model being rebuilt instead of reused? for details on each cause and how to diagnose them.

  • build_after vs lag_tolerance: Both configs reduce how often a model runs when upstream data is frequently fresh, but they work differently:

    • freshness.build_after (for example, {count: 4, period: hour}) skips the model unless the configured interval has elapsed and upstream sources have new data since the last run. A SQL change alone does not trigger a rebuild; both conditions must be met.
    • state.lag_tolerance (for example, 4h) skips the model unless upstream data is newer than the model's last run by at least the configured interval. Unlike build_after, a detected SQL change triggers a rebuild.
  • Efficient Testing not yet available: State-aware orchestration offers Efficient Testing (private beta); dbt State doesn't support it yet.

Was this page helpful?

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

0
Loading