defer_to_target
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.
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
Definition
defer_to_target specifies which target environment dbt State should defer to when resolving unselected upstream nodes and evaluating whether models need to be rebuilt.
In self-managed deployments with multiple environments, you can configure each target to defer to a different upstream environment. For example, a uat environment can defer to staging, while prod manages its own state independently.
Default
prod. When omitted, all targets defer to the target named prod. Use this config if you want to defer to a different target (for example, staging), or if your production target is named something other than prod (for example, production).
Example
Multi-environment deferral chain
Configure a pipeline where uat defers to staging:
my_project:
outputs:
dev:
type: snowflake
account: abc12345
database: ANALYTICS
schema: DBT_DEV
staging:
type: snowflake
account: abc12345
database: ANALYTICS
schema: DBT_STAGING
uat:
type: snowflake
account: abc12345
database: ANALYTICS
schema: DBT_UAT
defer_to_target: staging
prod:
type: snowflake
account: abc12345
database: ANALYTICS
schema: DBT_PROD
target: prod
Caveats to dbt State without a manifest
When dbt State tries to guess where the production version of a relation was built, it re-renders the database and schema names using the configured target from defer_to_target.
If either of the generated names depend on dynamic data that has changed since the production run, or the node's alias depends on any target-specific logic, then:
- The guessed location may not exist, forcing an unnecessary rebuild from scratch.
- The guessed location may point to the wrong object, resulting in invalid data.
The following examples show scenarios that will cause issues with an orders node. Assume the dev profile sets schema: dbt_developer and the prod profile sets schema: analytics.
Environment variables and CLI vars
If your schema name depends on an environment variable or a CLI var, dbt State may guess the wrong location because those values differ between production and local runs.
{% macro generate_schema_name(custom_schema_name, node) %}
{{ target.schema }}_{{ env_var('DBT_BRANCH', 'main') | replace('/', '_') }}
{% endmacro %}
- Production runs with
DBT_BRANCH=main, so the relation is built atanalytics_main.orders. - When a developer runs with
DBT_BRANCH=feature/x, dbt State swapstarget.schemato the prod value (analytics) but readsDBT_BRANCHfrom the developer's shell, producing the guessanalytics_feature_x.orders. - That relation does not exist in production, so no clone is performed and the node rebuilds from scratch.
The same issue occurs with CLI vars:
{% macro generate_schema_name(custom_schema_name, node) %}
{{ target.schema }}_{{ var('environment', 'dev') }}
{% endmacro %}
- Production runs
dbt run --vars '{environment: prod}', so the relation is built atanalytics_prod.orders. - When a developer runs
dbt runwith no--vars,var('environment')falls back to its default (dev), so dbt State guessesanalytics_dev.orders. - That relation does not exist in production. Vars passed at the original prod invocation are not stored anywhere dbt State can recover them.
Path-derived names when files move
A common pattern is to use a node's directory as its schema:
{% macro generate_schema_name(custom_schema_name, node) %}
{{ target.schema }}_{{ node.fqn[-2] }}
{% endmacro %}
- Production builds
models/finance/orders.sqlintoanalytics_finance.orders. - If a developer reorganizes the project and renames the directory to
models/accounting/, then runsdbt run -s orders, their local manifest records the node's parent directory asaccounting. dbt State then guessesanalytics_accounting.orders. - Production is still at
analytics_finance.orders, the clone misses, and the node rebuilds from scratch.
Target-specific generate_alias_name logic
Unlike database and schema, dbt State currently does not re-render aliases. An override on generate_alias_name that varies by target or environment breaks the guess.
{% macro generate_alias_name(custom_alias_name=none, node=none) %}
{%- if custom_alias_name -%}
{{ custom_alias_name | trim }}_{{ target.name }}
{%- else -%}
{{ node.name }}_{{ target.name }}
{%- endif -%}
{% endmacro %}
- When
target.name == 'prod', production buildsanalytics.orders_prod. - When a developer runs with
target.name == 'dev', dbt State swaps the schema component toanalyticsbut leaves the alias as-is, producing the guessanalytics.orders_dev.
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.
Related docs
Was this page helpful?
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.