16. Cheat sheet
dbt · 16. Cheat sheetEverything worth keeping within reach.
Commands
Section titled “Commands”dbt debug # test connection + config. start here.dbt deps # install packages from packages.ymldbt seed # load CSVs from seeds/dbt run # build modelsdbt test # run testsdbt snapshot # capture SCD2 historydbt build # seed + snapshot + run + test, in # graph order. USE THIS.dbt compile # render SQL, execute nothingdbt parse # parse only, write manifestdbt retry # re-run failures from last invocationdbt clean # delete target/ and dbt_packages/dbt ls # list selected resourcesdbt source freshness # check source stalenessdbt docs generate # manifest + catalogdbt docs serve # local docs sitedbt run-operation <macro> # run a macro standalonedbt show --select <model> # preview a model's resultsCommon flags
Section titled “Common flags”--select / -s what to build--exclude what to skip--target / -t which profile output--full-refresh rebuild incrementals from scratch--threads N override profile threads--vars '{"k": "v"}' override vars--state DIR directory with a previous manifest--defer resolve unbuilt refs from state--favor-state always prefer state for unselected nodes--fail-fast stop at first failure--empty build with zero rows (schema check)--no-partial-parse ignore the parse cacheSelection syntax
Section titled “Selection syntax”customers one model+customers it and all ancestorscustomers+ it and all descendants+customers+ its whole lineage2+customers two levels of ancestorscustomers+1 one level of descendants@customers ancestors, it, descendants, and their ancestors
"model_a model_b" union (space)"model_a,tag:finance" intersection (comma)--exclude tag:deprecated subtractionMethods
Section titled “Methods”tag:financepath:models/martsfile:customers.sqlpackage:dbt_utilsconfig.materialized:incrementalconfig.meta.contains_pii:truetest_type:unit | singular | generictest_name:uniquesource:jaffle_shop+exposure:executive_dashboardgroup:financeaccess:publicversion:latestresource_type:modelstate:new | modified | modified.body | modified.configsresult:error | fail | warn | successsource_status:fresherThe ones you will actually use
Section titled “The ones you will actually use”dbt build --select "state:modified+" --state ./prod \ --defer --favor-state # slim CIdbt build --select tag:hourly # by cadencedbt build --select +customers # a model and its inputsdbt retry # after a failuredbt build --exclude "test_type:unit" # productiondbt test --select "test_type:unit" # CIProject files
Section titled “Project files”dbt_project.yml the project. in git.profiles.yml the connection. NOT in git. default ~/.dbt/profiles.ymlpackages.yml dependenciespackage-lock.yml pinned versions. COMMIT THIS.# dbt_project.yml essentialsname: 'jaffle_shop'profile: 'jaffle_shop'require-dbt-version: [">=1.9.0", "<2.0.0"]
models: jaffle_shop: # ← project name, always +materialized: view staging: +materialized: view marts: +materialized: table +schema: martsMaterializations
Section titled “Materializations”| Build | Storage | Read | Use for | |
|---|---|---|---|---|
view |
instant | none | full query | staging, small |
table |
full | full copy | fast | marts |
incremental |
delta | full copy | fast | large, growing |
ephemeral |
none | none | inlined CTE | rarely |
materialized_view |
warehouse-managed | full copy | fast | live freshness |
Incremental
Section titled “Incremental”{{ config( materialized = 'incremental', unique_key = 'order_id', incremental_strategy = 'merge', on_schema_change = 'append_new_columns', cluster_by = ['order_date']) }}
select * from {{ ref('stg_orders') }}
{% if is_incremental() %}where updated_at > ( select dateadd(day, -3, max(updated_at)) from {{ this }}){% endif %}Strategies
Section titled “Strategies”append blind insert. immutable rows only.merge match on unique_key. THE DEFAULT.delete+insert for adapters without MERGE.insert_overwrite whole partitions. must be complete.microbatch 1.9+. time-batched, retryable, backfillable. event_time + batch_size.on_schema_change
Section titled “on_schema_change”ignore DANGEROUS. drops new columns silently.fail error and stop.append_new_columns THE SENSIBLE DEFAULT.sync_all_columns adds AND DROPS. data loss.- Test
uniqueonunique_key. Always. - Use a lookback window — a strict high-water mark drops late data forever.
- Lookbacks require an idempotent strategy (merge, not append).
- Deletes never arrive. Absence does not propagate.
- You should be able to
--full-refreshit.
models: - name: customers columns: - name: customer_id tests: [unique, not_null] - name: status tests: - accepted_values: values: ['active', 'churned'] - name: manager_id tests: - relationships: to: ref('employees') field: employee_id - name: address tests: - not_null: config: severity: warn error_if: ">1000" store_failures: true-- custom generic: tests/generic/test_positive.sql{% test positive(model, column_name) %}select * from {{ model }} where {{ column_name }} <= 0{% endtest %}# unit testunit_tests: - name: test_order_size model: orders given: - input: ref('stg_orders') rows: [{order_id: 1, amount: 150}] expect: rows: [{order_id: 1, size: 'large'}]A test is a query that should return zero rows.
Sources, seeds, snapshots
Section titled “Sources, seeds, snapshots”sources: - name: jaffle_shop database: raw schema: jaffle_shop loaded_at_field: _fivetran_synced freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} tables: - name: raw_orderssnapshots: - name: orders_snapshot relation: source('jaffle_shop', 'raw_orders') config: unique_key: order_id strategy: timestamp # or 'check' updated_at: updated_at invalidate_hard_deletes: trueSnapshots cannot be rebuilt. Never casually --full-refresh one.
Jinja context
Section titled “Jinja context”ref('model') another modelref('project','model') cross-projectsource('src','table') a sourcethis the current relationconfig(...) set configvar('name', default) project variableenv_var('NAME', default) environment variable — RETURNS A STRINGtarget.name 'dev' | 'prod' | 'ci'target.schema/.database the active target'sis_incremental() incremental stateexecute false during parse — GUARD run_queryrun_query(sql) execute at compile timelog(msg, info=True) print during a runadapter.dispatch(...) cross-warehouse macromodules.datetime / .rebuiltins.ref the pre-override versionPatterns
Section titled “Patterns”{# limit dev data — the highest-value pattern in dbt #}{% if target.name != 'prod' %}where event_date >= dateadd(day, -7, current_date){% endif %}
{# loop with trailing comma #}{% for m in methods %} sum(...) as {{ m }}{% if not loop.last %},{% endif %}{% endfor %}
{# macro #}{% macro cents_to_dollars(col, dp=2) %} round({{ col }} / 100.0, {{ dp }}){% endmacro %}
{# cross-adapter #}{% macro my_fn(x) %} {{ return(adapter.dispatch('my_fn')(x)) }}{% endmacro %}{% macro default__my_fn(x) %}...{% endmacro %}{% macro bigquery__my_fn(x) %}...{% endmacro %}Config precedence
Section titled “Config precedence”CLI flags > {{ config() }} > .yml > dbt_project.ymlscalars replaced (materialized, unique_key)lists CLOBBERED (tags — restate inherited ones!)dicts merged (meta)hooks APPENDED (all run, broad → narrow)Custom schema override
Section titled “Custom schema override”-- macros/generate_schema_name.sql{% macro generate_schema_name(custom_schema_name, node) -%} {%- if target.name == 'prod' and custom_schema_name is not none -%} {{ custom_schema_name | trim }} {%- elif custom_schema_name is none -%} {{ target.schema }} {%- else -%} {{ target.schema }}_{{ custom_schema_name | trim }} {%- endif -%}{%- endmacro %}Gate on target.name == 'prod', never on != 'dev'.
Artifacts
Section titled “Artifacts”target/manifest.json the project, resolvedtarget/run_results.json what happenedtarget/catalog.json real warehouse columnstarget/sources.json freshness resultstarget/partial_parse.msgpack the parse cachetarget/compiled/ YOUR SQL, Jinja resolvedtarget/run/ compiled SQL + DDLNever commit these. Publish manifest.json from production to object storage for slim CI.
Packages worth having
Section titled “Packages worth having”packages: - package: dbt-labs/dbt_utils # essential - package: calogica/dbt_expectations # more tests - package: dbt-labs/codegen # generate YAML - package: dbt-labs/audit_helper # compare relations - package: dbt-labs/dbt_project_evaluator # audit the projectTroubleshooting
Section titled “Troubleshooting”| Symptom | First thing to try |
|---|---|
| Cannot connect | dbt debug |
| Macro change has no effect | rm target/partial_parse.msgpack |
| Model does the wrong thing | read target/compiled/.../model.sql |
| Wrong config applied | dbt ls --select model --output json |
| Landed in the wrong schema | custom schemas concatenate — ch11 |
| Column missing after a run | on_schema_change was ignore |
| Duplicates appearing | unique_key is not unique — test it |
| Rows missing | strict high-water mark — add a lookback |
| Everything modified in CI | version mismatch or env_var in config |
| Nothing modified in CI | stale state manifest |
| CI used a stale relation | add --favor-state |
| Dashboard suddenly slow | view stacked on views — materialise |
| Tests pass, data is old | no source freshness check |
The ten rules
Section titled “The ten rules”ref()everywhere. A hard-coded name breaks ordering, environments, lineage and state selection at once.unique+not_nullon every primary key. The floor.dbt source freshnessbefore the build. Stale data passes every test.dbt build, notrunthentest. Failures stop the branch.- Marts are tables. Views stack badly.
- Incremental only when you have measured the pain — and always with a lookback and a uniqueness test.
- Set
on_schema_changeexplicitly. - Limit dev data with
target.name. The largest cost saving available. - Snapshots are irreplaceable data. Schedule them, back them up, never casually refresh.
- When the file stops looking like the SQL that runs, you have gone too far.
The guide
Section titled “The guide”- What dbt is, and why it exists
- The project
- Models and ref()
- Materializations
- Incremental models
- Sources, seeds and snapshots
- A dbt run traced
- Jinja and macros
- Tests and contracts
- Documentation and lineage
- Configuration and precedence
- State, artifacts and slim CI
- Tuning and operations
- Failure modes
- When to use dbt, and when not
- Cheat sheet — you are here