State selectors, dbt retry, result selectors, CI/CD with slim CI, and deployment environments โ the production operations layer of dbt.
Domain 6 covers how dbt manages state โ knowing what changed between runs โ and how that enables efficient CI/CD pipelines, production job recovery, and slim builds that only process what's new or modified.
Select models based on what changed since the last production run
Select based on outcome of the last run (error, warn, skip, pass)
Re-run only failed + downstream nodes from the last run automatically
Run only changed models in PRs โ fast, cost-effective CI pipelines
The most exam-tested deployment concept is Slim CI โ the pattern of running only changed models in CI rather than the full project:
This pattern makes CI 10x faster by only rebuilding models that actually changed โ not the entire project.
The exam tests two key concepts: (1) state:modified+ selects changed models AND their downstream dependencies โ the + is critical, without it you might miss testing a downstream model affected by your change. (2) dbt retry requires target/run_results.json to exist โ it reads the last run's results, so it must be run in the same environment/directory where the last run happened.
| Selector | What It Selects |
|---|---|
state:new | Models that exist in the project but don't exist in production artifacts |
state:modified | Models whose SQL or config changed since the last production run |
state:modified+ | Modified models + all their downstream dependencies (the slim CI standard) |
state:old | Models that exist in production but were removed from the project |
--state ./path/to/artifacts| Selector | What It Selects |
|---|---|
result:error | Nodes that errored in the last run |
result:error+ | Errored nodes + all their downstream dependencies |
result:warn | Nodes that produced warnings |
result:skip | Nodes that were skipped (due to upstream failures) |
result:pass | Nodes that passed (run or test) |
target/run_results.json--select result:error state:modified+dbt run --select result:error+ result:skipdbt retry re-runs all nodes that errored or were skipped in the most recent runtarget/run_results.json to determine which nodes need to be re-rundbt run --select result:error+ result:skip+--select result:error state:modified+--select result:error,result:skip--select result:error,tag:daily--select state:modified+--state flag pointing to production artifact directoryUnderstand what each selects and when to use each in a CI pipeline
Understand what each selects and the role of run_results.json
Requires run_results.json; re-runs error + skip nodes from last run
This is the standard pattern โ know it cold
manifest.json from last prod run is compared against current project state
Dev and CI reference production models for unchanged upstream dependencies
Verify only the failed + downstream models are re-run
Know what runs in each and how data flows through them
Not just the .sql file โ schema changes trigger modified too
Review all selector types and the --state flag requirement
5 questions on state, retry, and deployment.
3โ4 days to cover state, retry, and CI patterns.
Missing downstream impact of changes
state:modified selects only the changed model itself. If you change stg_orders, fct_orders (which depends on it) is NOT selected and won't be tested in CI. You might merge a breaking change without knowing.
Always use state:modified+ in CI pipelines. The + ensures all downstream dependencies of changed models are also built and tested, catching cascading failures.
retry needs run_results.json from the failed run
dbt retry reads target/run_results.json. If you run it from a different directory, or the previous run's artifacts were cleaned, retry fails with "no run results found".
Run dbt retry in the same project directory where the original failing run happened, ensuring target/run_results.json is still present. In dbt Cloud, retry is available directly from the run UI.
State uses manifest.json, not run_results.json
Candidates confuse the artifacts needed for state selectors vs result selectors. State comparison needs manifest.json (from the last production run). Result selectors need run_results.json (from the last run in the current directory).
State selectors (state:modified) โ need production manifest.json via --state flag. Result selectors (result:error) โ read local target/run_results.json automatically.
New models aren't "modified" โ they won't be selected
A developer adds a new model. state:modified only selects models that EXIST in both the current project and the production artifacts and have changed. New models are not in the production artifacts, so they're not "modified".
Use both: --select state:new state:modified+. This ensures new models AND modified models (with their downstream) are all built and tested in CI.
Environments and targets are related but distinct
Candidates conflate dbt Cloud environments (dev, CI, prod) with the --target flag in profiles.yml. They're related but different: environments are dbt Cloud concepts; targets are connection profiles.
A dbt Cloud environment defines the credentials, schema, and target name for a deployment context. The --target flag selects which profile to use when running locally. They serve the same conceptual purpose but at different levels.
--state flag points to a directory containing the production manifest.json file (not the file itself). dbt reads the manifest.json from that directory to compare the current project's state against the last production run. In dbt Cloud CI jobs, this is typically fetched automatically from the production environment's last successful run.dbt retry only re-runs the nodes that failed (ERROR) or were skipped (SKIP) in the previous run. It does NOT re-run nodes that already succeeded. This makes recovery faster and avoids redundant compute โ if 90% of models succeeded, retry only touches the 10% that didn't.--select flags to combine selectors. For example: dbt build --select state:modified+ result:error --state ./artifacts. The two selectors are combined with AND logic, selecting nodes that are BOTH modified AND errored. Use commas for OR logic: --select result:error,result:skip.--select result:error+ result:skip โ both error and skip nodes need to be addressed.