CertSafari
    DBT Architect· Lessons

    Domain 3 · Lesson 15/39

    Configuring deferral to staging and production environments

    Configuring dbt to allow deferral to other environments

    13 min read
    2.56% of exam
    7 sources
    Published 13 Oct 2026
    Docs as of 12 Oct 2026

    What you will be able to do

    • Trace how dbt resolves a ref under deferral: development first, then staging, then production
    • Prepare a deployment environment so it can serve as a deferral target
    • Enable or disable deferral in the Studio IDE and the dbt platform CLI
    • Point deferral at a specific environment with defer-env-id
    • Configure deferral outside the dbt platform with --defer, --state and defer_to_target

    Key concept

    Deferral — Deferral lets dbt run only the nodes you selected. Any upstream ref you did not build resolves to the relation that already exists in another environment, located from that environment's manifest. On the dbt platform, that environment is Staging when one exists and Production otherwise.

    1.How a deferred ref finds its parent

    Deferral saves you from rebuilding a whole upstream DAG just to test one model. Say a developer edits model_b, which selects from {{ ref('model_a') }}, and their development schema dev_alice is empty. A plain dbt run --select "model_b" compiles to from dev_alice.model_a, and the query fails because that relation does not exist. Add deferral and the same ref compiles to prod.model_a, so the run succeeds without anyone building model_a first.

    For each ref, dbt checks locations in a fixed order. A relation in your development schema wins. If there isn't one, dbt uses the parent's location as recorded in the staging environment's metadata. If there is no staging environment either, it uses the production environment's metadata. Each invocation defers to a single environment, never a mix of staging for some parents and production for others.

    Two exceptions change this order. Passing --favor-state skips the first step: refs resolve from staging or production metadata even when a development relation exists. Ephemeral models are never deferred at all, because they compile inline into whatever references them. In the dbt platform, a ref is only deferred when the node is not among the selected nodes. A model you selected always builds in your own schema.

    Checkpoint 1 of 8· Put it in order

    Put the locations dbt tries, when deferral is on and no --favor-state is passed, in the order it tries them

    1. 1.The parent's location from the production environment's metadata
    2. 2.The parent's location from the staging environment's metadata
    3. 3.The relation in the developer's own development schema

    Checkpoint 2 of 8· Exam question

    A dbt Cloud project has both a 'Staging' environment and a 'Production' environment configured. A developer runs `dbt build --select model_a --defer` from the Studio IDE, and `model_a`'s upstream dependency `stg_orders` does not exist in the developer's own development schema. Which environment's build artifacts will dbt resolve `ref('stg_orders')` against?

    Sources12

    2.What makes an environment a deferral target

    Deferral reads artifacts from a deployment environment, so that environment has to be set up correctly first. Every deployment environment has a deployment type: General, Staging or Production. Creating these environments is covered in [creating deployment environments](lesson:3.5). For deferral, the type you choose decides whether the environment can be a target at all.

    Deployment types and how deferral treats them
    Deployment typeHow many per projectRole in default deferral
    Production1Fallback target when no Staging environment exists
    Staging1Preferred target whenever it is defined
    GeneralAny numberNot chosen by default

    The Production environment checkbox in Environment Settings is the starting point. Only one deployment environment per project can carry it. That environment also needs at least one successful job run, because a run is what produces the manifest that deferral compares against. Not every run qualifies: dbt uses the most recent successful production job and ignores CI jobs.

    Adding a Staging environment changes the default target straight away, and that can break things. Once a Staging environment exists, the Studio IDE looks for its artifacts first. If no deploy job has run there yet, there is no metadata to defer to, and defer in the IDE stops working until a deploy job succeeds in Staging. Teams add Staging to keep developers away from production data. Developers still get metadata-powered features like deferral, while the Production environment stays locked down with environment-level permissions.

    Checkpoint 3 of 8· Check yourself

    A team creates a new Staging environment on Monday to keep developers off production data. Deploy jobs are scheduled to start running there on Friday. What happens when developers use Defer to staging/production in the Studio IDE on Tuesday?

    Sources134

    3.Turning deferral on in the Studio IDE and the platform CLI

    The two development tools have opposite defaults. In the Studio IDE, deferral is opt-in: you toggle Defer to staging/production on the command bar. dbt then pulls the latest manifest from the staging or production environment and adds --defer to every command that accepts it. Start a branch with an empty development schema, edit one model and run dbt build -s state:modified, and only the edited model runs. Its refs resolve to staging or production.

    The dbt platform CLI defers on every invocation automatically, comparing against production artifacts. To build a model's parents into your own schema instead, pass --no-defer. Automatic deferral only works if the CLI can tie your local project to a dbt platform project. That means dbt_project.yml must declare the project id that matches your dbt_cloud.yml.

    The project id the dbt platform CLI needs in dbt_project.yml for automatic deferralyaml
    dbt-cloud:
      project-id: '654321'

    Checkpoint 4 of 8· Check yourself

    A developer using the dbt platform CLI wants one run that builds a model's upstream parents into their own development schema instead of reading them from production. What do they do?

    Checkpoint 5 of 8· Exam question

    A dbt Cloud administrator wants automatic deferral to work correctly for a CI job that compares pull request changes against production. Which two conditions must be true for this to function? (Select two.)(Select 2)

    Sources1

    4.Choosing the environment with defer-env-id

    The Staging-then-Production default is only a default. You can defer to any environment by setting a defer-env-id key to that environment's id. Where you put the key determines which tools use it. In dbt_project.yml it applies to both the dbt platform CLI and the Studio IDE. In dbt_cloud.yml it applies only to the platform CLI. The file you choose decides whether IDE developers get the override.

    defer-env-id in dbt_cloud.yml, which only the dbt platform CLI readsyaml
    context:
      active-host: ...
      active-project: ...
      defer-env-id: '123456'

    Setting the key has a cost if your account uses dbt State. defer-env-id works from a manifest, so it turns off the dbt State-powered state:* selectors that compare each node against its own last execution. Without the key, dbt State defers to production by default. Add defer-env-id only when you actually need a different target, such as Staging.

    Checkpoint 6 of 8· Fill the gap

    Complete the dbt_project.yml block so that both the Studio IDE and the platform CLI defer to environment 123456.

    dbt-cloud:
      project-id: '654321'
       ? : '123456'

    Checkpoint 7 of 8· Exam question

    In dbt Cloud, what does the `--favor-state` flag change about how `--defer` resolves `ref()` calls, compared to default deferral behavior?

    Sources15

    5.Deferral outside the dbt platform

    Outside the dbt platform, nothing defers automatically. You have to supply both a manifest and the instruction to use it. --defer turns deferral on and --state points at the directory holding a previous run's manifest.json. Deferral needs both. Copy the artifacts from a production run into a local folder, then pass that folder on each command.

    Deferring run and test to a manifest stored locallybash
    dbt run --select [...] --defer --state path/to/artifacts
    dbt test --select [...] --defer --state path/to/artifacts

    Each flag has a matching environment variable: DBT_ENGINE_DEFER, DBT_ENGINE_STATE and DBT_ENGINE_DEFER_STATE. If a flag and its variable are both set, the flag wins. --defer-state is optional. It lets you compare state:modified against one manifest while deferring unbuilt parents to another. When you leave it out, deferral uses the --state manifest. That is usually what you want: compare against production and fall back to production.

    Self-managed deployments with dbt State enabled have a third option: set defer_to_target in profiles.yml. It names the target that dbt State defers to, and when it is omitted every target defers to the one named prod. On the dbt platform this setting does nothing, because deferral there is configured on the environment. Without a manifest, dbt State guesses each parent's location by re-rendering database and schema names against that target. A generate_alias_name macro that varies by target is the riskiest case, since a wrong guess can corrupt data. If you have one, supply a manifest.json. For when to choose this setup over self-deferral or a CI job that defers, see [choosing a deferral type](lesson:4.11).

    A uat target that defers to staging, while prod manages its own stateyaml
    my_project:
      outputs:
        dev:
          type: snowflake
          # ... dev connection settings
        staging:
          type: snowflake
          # ... staging connection settings
        uat:
          type: snowflake
          # ... uat connection settings
          defer_to_target: staging
        prod:
          type: snowflake
          # ... prod connection settings
      target: prod

    Checkpoint 8 of 8· Match them up

    Match each self-managed setting to what it does

    Tap a term, then the definition that fits it.

    Sources267

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.With deferral on, the dbt platform always resolves unbuilt parents to Production.Why is that wrong?

      If a Staging environment is defined, dbt prefers its metadata and only falls back to Production when there is no Staging environment.

      Covered in How a deferred ref finds its parent

    2. 2.Setting defer-env-id in dbt_cloud.yml changes the deferral target for the Studio IDE too.Why is that wrong?

      Only dbt_project.yml applies to both tools. dbt_cloud.yml is read by the dbt platform CLI alone.

      Covered in Choosing the environment with defer-env-id

    3. 3.Passing --defer on its own is enough to defer in a self-managed run.Why is that wrong?

      Deferral needs a manifest as well, so --state (or DBT_ENGINE_STATE) has to be set alongside --defer.

      Covered in Deferral outside the dbt platform

    4. 4.Adding defer_to_target to profiles.yml changes which environment the dbt platform defers to.Why is that wrong?

      defer_to_target is for self-managed deployments only. On the dbt platform, deferral is configured in the environment settings.

      Covered in Deferral outside the dbt platform

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Note that dbt only defers to one environment per invocation — either staging or production.”
      ↩︎ How a deferred ref finds its parent
      “Passing the --favor-state flag will always resolve refs using staging metadata if available”
      ↩︎ How a deferred ref finds its parent
      “You must select the Production environment checkbox in the Environment Settings page. This can be set for one deployment environment per dbt project.”
      ↩︎ What makes an environment a deferral target
      “When using defer, it compares artifacts from the most recent successful production job, excluding CI jobs.”
      ↩︎ What makes an environment a deferral target
      “To enable defer in the Studio IDE, toggle the Defer to staging/production button on the command bar.”
      ↩︎ Turning deferral on in the Studio IDE and the platform CLI
      “A dbt platform project id must be declared in your dbt_project.yml for automatic deferral”
      ↩︎ Turning deferral on in the Studio IDE and the platform CLI
      “(dbt platform CLI and Studio IDE) or dbt_cloud.yml (dbt platform CLI only) file”
      ↩︎ Choosing the environment with defer-env-id
      “dbt powers this by using a production manifest for comparison”
      ↩︎ Key concept
      “By default, dbt will prefer metadata from the project's "Staging" environment (if defined). Otherwise, it uses "Production."”
      ↩︎ Exam trap 1
      “(dbt platform CLI and Studio IDE) or dbt_cloud.yml (dbt platform CLI only) file”
      ↩︎ Exam trap 2
      “If a development version of a deferred relation exists, dbt preferentially uses the development database location when resolving the reference.”
      ↩︎ Prediction
      “If a development version doesn't exist, dbt uses the staging locations of parent relations based on metadata from the staging environment.”
      ↩︎ Checkpoint
      “The defer feature in the Studio IDE won't work if a Staging environment exists but no deploy job has run.”
      ↩︎ Checkpoint
      “--defer is automatically enabled in the dbt platform CLI for all invocations, compared with production artifacts. You can disable it with the --no-defer flag.”
      ↩︎ Checkpoint
    2. 2.
      “Ephemeral models are never deferred, since they serve as "passthroughs" for other ref calls.”
      ↩︎ How a deferred ref finds its parent
      “If you apply environment-specific limits in development but not in production, you may select more data than expected.”
      ↩︎ How a deferred ref finds its parent
      “Deferral requires both --defer and --state to be set, either by passing flags explicitly or by setting environment variables”
      ↩︎ Deferral outside the dbt platform
      “Deferral requires both --defer and --state to be set, either by passing flags explicitly or by setting environment variables”
      ↩︎ Exam trap 3
      “If --defer-state is not specified, deferral will use the manifest supplied to --state.”
      ↩︎ Checkpoint
    3. 3.
      “can have any number of General deployment environments, one Production deployment environment and one Staging deployment environment.”
      ↩︎ What makes an environment a deferral target
    4. 4.
      “Staging: Environment for working with production tools while limiting access to production data.”
      ↩︎ What makes an environment a deferral target
    5. 5.
      “defer-env-id is manifest-based. If you set it, dbt State-powered state:* selectors are disabled.”
      ↩︎ Choosing the environment with defer-env-id
      “By default, dbt State defers to your production environment.”
      ↩︎ Choosing the environment with defer-env-id
    6. 6.
      “If both the flag and env var are provided, the flag takes precedence.”
      ↩︎ Deferral outside the dbt platform
    7. 7.
      “When omitted, all targets defer to the target named prod.”
      ↩︎ Deferral outside the dbt platform
      “This scenario is the most likely to cause data corruption. If you have custom generate_alias_name logic, provide a manifest.json to guarantee accurate results.”
      ↩︎ Deferral outside the dbt platform
      “This configuration applies to self-managed dbt deployments. If you're using the dbt platform, deferral is configured through your environment settings in the UI.”
      ↩︎ Exam trap 4

    Ready to test yourself?

    Practise the 9 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.