Leveraging the dbt state: sample questions

3 free practice questions on leveraging the dbt state, one of the seven topics in the official v1.11 outline for the dbt Analytics Engineering Certification Exam — an estimated 6% of the exam, or about 4 of its 65 questions. Answers, reasoning and documentation links are all on this page.

Last updated . We revise these pages whenever dbt Labs revises the exam.

SHARE OF THE EXAM~6%our estimate
QUESTIONS HERE30 with runnable SQL
FORMATS SHOWN3of 6 on the exam

What this topic covers

Two subtopics: understanding state and state selection, which is what makes slim CI possible, and using dbt retry.

SUBTOPICS, FROM THE OFFICIAL OUTLINE · 2

  1. 01Understanding state and state selection
  2. 02Using dbt retry

Where the marks go

Both turn on which artifact is being read, and that is the single thing to get straight. State selection diffs the current project against a manifest.json supplied with --state, and the sub-selectors are not interchangeable: state:modified flags resources whose definitions changed, state:new flags resources with no counterpart in that manifest at all.

dbt retry keeps no state of its own. It re-runs from the point of failure recorded in the previous invocation's run_results.json — so a run killed by a CI timeout, which never gets to write that file, leaves retry acting on an older run's results. The third question walks through exactly that sequence.

3 sample questions, with answers

Nothing is hidden. Each question shows the correct answer, why it is right, why every other option is wrong, and the documentation page that settles it. Where the answer is a claim about SQL behaviour, there is a query you can run in the browser against a small sample schema.

Q1Fill in the blankMedium

A CI job downloads production's manifest.json into ./prod-artifacts. You want dbt build to compare the current project against those artifacts and build only the modified resources. Complete the command: dbt build --select state:modified ______ ./prod-artifacts

In the exam you type the answer. What counts as correct is below.

ACCEPTED ANSWERS--state · state · --state ./prod-artifacts · --state ./prod-artifacts/

WHY

The state selection methods (state:modified, state:new, and their sub-selectors) work by diffing the current project against a manifest.json produced by an earlier dbt invocation. dbt does not find that manifest on its own — the --state flag names the directory that holds the previous run's artifacts, and dbt reads manifest.json from it (plus run_results.json for result: selectors and sources.json for source_status:). Without --state, any selector using a state method fails, because there is no comparison manifest to diff against. The equivalent environment variable is DBT_STATE, which is useful in CI where the path is set once for the whole job. Note that --state is separate from --defer: --defer tells dbt to resolve ref() calls for unselected, unbuilt models to the relations recorded in that manifest, and it also depends on --state (or --defer-state) to know where the manifest lives. So --state supplies the artifacts; --select state:modified decides what to do with the diff.

Q2Multiple choiceMedium

Last night's dbt build never reached a model: the warehouse refused the connection and the invocation failed immediately. This morning the credentials are fixed. You run dbt retry in the same project directory. What happens?

# last night
dbt build --select tag:nightly
# this morning, after fixing credentials
dbt retry
  • Nothing runs, because the failed invocation recorded no nodes to resume from; you re-issue the original build.CORRECT
  • The whole tag:nightly selection is rebuilt, because retry falls back to the original command when no node failed.
  • Retry resumes at the first node of the DAG, since the point of failure precedes every model.
  • Nothing runs, because retry treats the previous invocation as having completed successfully.
  • Retry errors out, because no run_results.json was written for the failed invocation.

WHY

dbt retry resumes work; it does not reconstruct it. "Retry references run_results.json to determine where to start", and it "re-executes the last invocation from the point of failure" — so it needs a recorded point of failure among the nodes. A run that dies before any node executes gives it nothing to anchor to, and the docs call out this exact case: "If no nodes are executed before the failure (for example, if a run failed early due to a warehouse connection or permission errors), retry won't run anything since there are no recorded nodes to retry from." A refused connection is one of the page's own two examples. The documented remedy is equally explicit: "we recommend checking your run_results.json file and manually re-running the full job so the nodes build." The rule worth carrying out of this: retry's usefulness scales with how far the previous run got. "Once some nodes have run, you can use retry to re-execute from any new point of failure" — but a failure at connection time is precisely the case where retry has nothing to offer, and reaching for it costs you a night.

WHY THE OTHERS ARE WRONG

The whole tag:nightly selection is rebuilt, because retry falls back to the original command when no node failed.
Retry has no fallback to the original command. The docs say the opposite for this case — with no recorded nodes it "won't run anything" — and re-running the full job is described as something you do manually, not something retry does for you.
Retry resumes at the first node of the DAG, since the point of failure precedes every model.
There is no such resumption point. Retry starts from a point of failure recorded among the executed nodes, and here no node executed; the failure happened before the graph was reached, not at its first node.
Nothing runs, because retry treats the previous invocation as having completed successfully.
Right outcome, wrong reason — and the reason is the discrimination. The docs do say that "if the previously executed command completed successfully, retry will finish as no operation", but last night's command did not complete successfully; it failed. Nothing runs because no nodes were recorded, not because there was nothing left to do.
Retry errors out, because no run_results.json was written for the failed invocation.
Retry does not error here, and the artifact is not the problem. The docs' own recommendation for this situation is to check your run_results.json file, which presumes it exists; what it lacks is executed nodes to resume from.
Q3Discrete option (DOMC)Medium

You run the command below in a dev target where some upstream models have been built and others have never been built. You will be shown statements about what --defer does here one at a time. For each statement, answer YES if it is true, NO if it is false.

dbt build --select state:modified+ --defer --state ./prod

In the exam these appear one at a time and you answer YES or NO to each, without seeing the rest. All of them, with their answers, are below.

  • Unselected upstream models with no relation in the dev target resolve to their relations in ./prod.YES
  • The unmodified upstream parents are added to the run and built in dev before their children.NO
  • An unselected upstream model that already exists in the dev target resolves to that dev relation.YES
  • Adding --favor-state resolves refs to ./prod even for unselected models that exist in the dev target.YES
  • Dropping --defer would narrow the set of nodes state:modified+ selects.NO
  • Deferral takes effect from --defer alone, so --state is optional.NO

WHY

--defer changes one thing only: how ref() resolves, and only for nodes dbt is not building. dbt applies two criteria to each referenced node — is it included in the current run's selection, and does it exist as a relation in the current environment? A ref to a node that is neither selected nor present in the target resolves to that node's relation recorded in the --state manifest (a), which is what lets a slim CI or dev run read production upstreams instead of rebuilding them. If the unselected node does exist in the target, dbt keeps the local relation (c), because the second criterion is satisfied. --favor-state exists to skip exactly that second check: with it, dbt prioritizes the node definition from the --state directory even when the relation exists in the current target (d). The carve-out is worth memorising, because it is the first criterion reasserting itself — this does not apply if the node is also part of the selected nodes. A model dbt is building is built, never deferred, whatever --favor-state says. Selection is untouched throughout — state:modified+ compares the current project against the manifest.json in ./prod with or without --defer.

WHY THE OTHERS ARE WRONG

The unmodified upstream parents are added to the run and built in dev before their children.
Deferral never adds nodes to the run. --select state:modified+ fixes the selection; --defer only rewrites ref() resolution for nodes outside that selection, which is precisely why the unmodified parents are never built in dev.
Dropping --defer would narrow the set of nodes state:modified+ selects.
state:modified+ compares the current project to the manifest.json supplied by --state, and that comparison is independent of --defer. Remove --defer and the same nodes are selected; they simply resolve refs to dev relations that may not exist, so the run fails instead of reading ./prod.
Deferral takes effect from --defer alone, so --state is optional.
Deferral requires both --defer and --state (as flags or via the DBT_DEFER and DBT_STATE environment variables). --state supplies the manifest whose relations the deferred refs point at, so --defer on its own has no namespace to defer to.

Know whether leveraging the dbt state is actually costing you marks.

The free readiness check is weighted like the real exam across all seven topics, so it tells you where you stand on this topic relative to the rest — which is the only version of that question worth answering before you book.

Take the free readiness check20 questions · ~15 minutes · no card

The other six topics

Keep reading

SOURCES

Every source above was read in full and last checked on .