dbt Cheat Sheet

dbt Commands & Selectors (data build tool)

The dbt (data build tool) cheat sheet: `dbt build` builds and tests selected resources in DAG order, `dbt run` builds only models and `dbt test` only runs tests. Graph operators such as `my_model+` choose what runs. It starts with the dbt Core commands and selection syntax, and ends with the flags and the order of a first build.

Last updated: Proudly published by: Jeff Wahl10 min read

dbt commands cheat sheet for dbt Core

dbt (data build tool) is run from the command line, and about a dozen commands cover daily work. dbt build builds and tests. dbt run and dbt test cover each half, while dbt seed and dbt snapshot handle the other resource types. dbt compile and dbt show let you look before you build, as does dbt list. Almost every command takes --select and --exclude, so the skill that pays off most is selecting the right nodes.

This page covers dbt Core, the open source command line tool, and follows the dbt command reference. Where a behavior depends on a version, the version is named. Everything else holds for all supported versions, according to that reference.

dbt commands at a glance

Build, test and change data
dbt buildrun and test in DAG order
dbt runbuild models
dbt testrun data and unit tests
dbt seedload CSV files
dbt snapshotrecord row changes
dbt run-operationcall a macro
dbt retryresume from failure
dbt clonecopy from a prior state
Set up, inspect and document
dbt initcreate a project
dbt debugcheck connection and setup
dbt depsinstall packages
dbt compilerender SQL only
dbt parseparse and time the project
dbt listlist resources
dbt showpreview rows
dbt cleandelete artifacts
dbt docs generatebuild the docs site
dbt source freshnesscheck source staleness

dbt build vs dbt run vs dbt test

dbt run builds models only. dbt test runs the unit tests defined on SQL models and the data tests defined on models and sources. Data tests on snapshots and seeds run too. dbt build does both in DAG order and also handles seeds and snapshots, so a seed loads before the model that reads it and a model is tested before its children are built.

The ordering has a consequence that run then test does not have. In dbt build, a failing test on an upstream resource blocks the resources downstream of it, and they're skipped entirely. To let a test report without blocking, set its severity to warn. Run as 2 commands, dbt run would already have built every child on the bad data before dbt test found the problem.

To split the tests by kind, use the test_type selector. dbt test --select test_type:data or dbt test --select test_type:unit makes the first split, and test_type:singular or test_type:generic divides the data tests by how they are defined. The --empty flag on run and build limits refs and sources to zero rows. dbt still executes the model SQL against the warehouse, so it validates the project without reading the input data.

dbt run --full-refresh (short form -f) treats incremental models as table models, and is_incremental() returns false for every model during that run. Use it after an incremental model's schema or logic changes. How incremental models decide which rows to process is covered on its own page.

dbt select syntax cheat sheet

# a model, a folder, a package
dbt run --select "my_model"
dbt run --select "path/to/models"
dbt run --select "my_package.some_model"

# by tag, by config, by group
dbt run --select "tag:nightly"
dbt run --select "config.materialized:incremental"
dbt run --select "group:finance"

# union is a space, intersection is a comma with no space
dbt run --select "tag:nightly my_model finance.base.*"
dbt run --select "marts.finance,tag:nightly"

# everything except
dbt run --select "my_package.*+" --exclude "my_package.a_big_model+"

# models that read from a source, and the tests on one model
dbt run --select "source:snowplow+"
dbt test --select "one_specific_model,test_type:data"

Selection examples from the dbt documentation. Quote each selector so the shell doesn't expand it

dbt graph operators: +, n+ and @

A plus after a name selects the resource and its descendants, a plus before selects it and its ancestors, and a plus on both sides selects both. A number limits the steps: my_model+1 is the model and its first-degree descendants, 2+my_model adds the parents and grandparents, and 3+my_model+4 does both at once.

The @ operator is valid only at the front of a name. It selects the model together with everything downstream of it, then adds the ancestors of those descendants. Take a project of 7 models in which fct_orders has 2 parents named my_model and stg_b. my_model+1 picks 2 models and my_model+ picks 3. +my_model+ picks 5. @my_model picks all 7, because it also adds stg_b and raw_b, the other ancestors of a descendant.

A graph of 7 dbt models, raw_a, stg_a, my_model, fct_orders, dashboard, raw_b and stg_b, and 4 copies of it with the models each selector picks filled in: my_model+1 picks 2, my_model+ picks 3, +my_model+ picks 5 and @my_model picks all 7A graph of 7 dbt models, raw_a, stg_a, my_model, fct_orders, dashboard, raw_b and stg_b, and 4 copies of it with the models each selector picks filled in: my_model+1 picks 2, my_model+ picks 3, +my_model+ picks 5 and @my_model picks all 7

That is why @ exists. In a continuous integration schema where the ancestors of your descendants have not been built yet, +my_model+ builds a descendant whose other parent is missing and fails, and the dbt documentation recommends @ for that case. For day to day work on 1 model, my_model+ is the common choice.

Prepare for the interview
01 / Open invite
02min.

Know dbt commands the way the interviewer who asks it knows it.

a dbt commands query, the same shape a screen would give you.
The diff against expected. Where ties broke. What you missed.
sandbox
1SELECT user_id,
2 COUNT(*) AS sessions
3FROM events
4WHERE ts >= NOW() - INTERVAL '7 day'
5
Execute your solution0.4s avg.
MicrosoftInterview question
Solve a dbt commands problem

dbt selector methods: tag, path, config, source, state and more

A selector can name a resource or use a method before a colon. The documented methods include tag: and config., the latter followed by a config such as materialized. Next are source: and package:, then fqn: and group:, with access: last. The list continues with exposure: and metric:, then test_type: and test_name:. After those come unit_test: and state:, and the last two are result: and version:. The path: and file: methods apply to dbt v1.11 and later, as do the resource_type: method and source_status:.

2 methods suit pipeline work. source:snowplow+ selects the models that read from a source, and +exposure:weekly_kpis selects everything that feeds an exposure, so you can rebuild just what a dashboard depends on. test_name:unique selects every test of the generic unique test across the project.

dbt list (or dbt ls) prints what a selector would pick without running anything, and it does not connect to the database. Check a complicated selector there first with dbt ls --select "tag:nightly" --resource-type test. Set --output to json or name to pick the format; path or selector work as well. The node selection syntax reference has the full method list.

How to run only what changed or failed: state, result, retry and clone

The state: method compares the project with a previous manifest, so dbt run --select "state:modified" --state path/to/artifacts builds only the nodes that differ from the artifacts in that directory. Add the plus for the children, as in state:modified+. The result: method does the same with a prior run's outcomes, so dbt run --select "result:error" --state path/to/artifacts picks the resources that failed last time.

dbt retry is the shorter route for the common case. It reads run_results.json from the last invocation and re-executes from the point of failure, so after you fix a failed customers model it rebuilds that model and not its upstream dependencies. It needs dbt v1.6 or later, and the docs list the commands it covers. The list opens with build and compile, then clone and docs generate, then seed and snapshot, test and run, with run-operation last.

Its limits are plain. If the previous command succeeded, retry finishes as a no operation. If the failure came before any node ran, such as a bad warehouse connection, no nodes were recorded and retry runs nothing, so you rerun the full command. Retrying without fixing the cause yields the same failure.

dbt clone --state path/to/artifacts copies selected models from that state into the target schema. Where the platform supports zero-copy clones of tables, which Snowflake and Databricks do and BigQuery does too, dbt creates a clone, and otherwise it creates a view that selects from the source object. By default it does not recreate relations that already exist, and --full-refresh overrides that. It needs dbt v1.6 or later.

Common dbt flags

# pick and remove resources (short form -s)
dbt build --select "tag:nightly" --exclude "my_model"

# rebuild incremental models as tables, reload seeds (short form -f)
dbt run --full-refresh

# validate SQL and dependencies with zero input rows
dbt build --empty

# stop at the first failure for this invocation, or turn it off
dbt run --fail-fast
dbt run --no-fail-fast

# compare against a prior run's artifacts
dbt run --select "state:modified+" --state path/to/artifacts

# more parallelism, useful for clone because its statements are independent
dbt clone --state path/to/artifacts --threads 50

# variables, passed as a quoted dictionary
dbt snapshot --select my_snapshot --vars '{"cutoff_date": "2026-01-01"}'

# macro arguments, passed as a YAML string
dbt run-operation clean_stale_models --args '{days: 7, dry_run: True}'

# rows shown by dbt show, 5 by default
dbt show --select my_model --limit 20

Flags go after the dbt prefix and the subcommand, as the documentation advises

dbt source freshness, seed, snapshot and run-operation

dbt source freshness checks whether sources meet the staleness thresholds in their config. It writes target/sources.json, and when a table is stale it reports a warning or an error and exits with a nonzero exit code, which is what a scheduler needs to see. Select part of the set with --select "source:snowplow.event". In the YAML, the freshness block moved under config in dbt v1.9 and loaded_at_field in v1.10.

dbt seed loads the CSV files in seed-paths as tables and suits small reference data such as country codes. --full-refresh forces a full reload when the file's columns or types change. dbt seed --empty, available in dbt v1.12 and later, creates the tables with the right schema and no rows. That lets downstream models run in development or CI, and unit tests too.

dbt snapshot records changes to a source over time as a type-2 slowly changing dimension, so run it on a schedule. Snapshots ignore --full-refresh, which means dbt build --full-refresh runs a snapshot as normal and keeps its history.

dbt run-operation calls a macro by name, with arguments as a YAML string: dbt run-operation clean_stale_models --args '{days: 7, dry_run: True}'. It is the route for grants and other maintenance SQL that is not a model.

The commands for a first dbt build, in order

  1. 01

    dbt init

    Creates a new project and the folder structure that the other commands expect.

  2. 02

    dbt debug

    Checks the database connection and the project configuration, plus the installed versions, before anything runs.

  3. 03

    dbt deps

    Installs the packages listed in packages.yml and writes package-lock.yml, which records the exact versions.

  4. 04

    dbt seed

    Loads the CSV reference data that models read through ref.

  5. 05

    dbt build

    Builds models in DAG order, running tests and snapshots as it goes. It skips whatever sits downstream of a failure.

  6. 06

    dbt docs generate

    Generates the documentation site from the project and its lineage.

dbt deps, debug, compile and clean

dbt deps installs the packages in packages.yml and writes package-lock.yml. While packages.yml is unchanged, it installs the locked versions, so commit the lock file. dbt deps --upgrade forces an update of every package and can change your builds, --lock updates the lock file without installing, and --add-package dbt-labs/dbt_utils@1.0.0 adds an entry.

dbt debug is a command, not the --debug flag, which only raises log verbosity. It checks the connection, dbt_project.yml, the system environment, required dependencies such as git, and the adapter. dbt debug --connection tests only the connection, and --config-dir prints how to reach the folder where dbt looks for profiles.yml.

dbt compile renders each model's SQL into target/compiled/ without running it, which is the fastest way to read what a Jinja macro produced. dbt show --select my_model runs the compiled query and prints the first 5 rows, and the --limit flag wraps the query in a SQL limit, so the warehouse returns only that many rows. dbt clean deletes the artifacts of the project, and dbt parse parses the project and writes timing information.

What data engineering interviews ask about dbt commands

Interviewers rarely ask for flag names. They ask what you would run in a situation: a nightly job that failed on model 14 of 40, a pull request that should build only the changed models, an incremental model whose logic changed. The answers on this page map straight onto them. dbt retry or result:error come first. state:modified+ and --full-refresh follow. The dbt interview questions cover dbt models and tests as well as sources in that style.

Most dbt work is SQL, so the other half of preparation is the SQL itself. The SQL interview questions and the SQL practice problems cover the queries your models contain, and the data engineer interview prep guide shows where dbt fits in the loop.

dbt commands FAQ

What are the main dbt commands?+
`dbt run` builds models and `dbt test` runs tests. `dbt build` runs everything selected in DAG order, and that covers seeds as well as snapshots. `dbt seed` loads CSV files and `dbt snapshot` records changes over time. `dbt compile` renders SQL without running it. `dbt deps` installs packages and `dbt debug` checks the connection, while `dbt docs generate` builds documentation.
What is the difference between dbt run and dbt build?+
`dbt run` builds only models. `dbt build` builds models in DAG order and also runs tests, and it handles seeds and snapshots in the same pass. A failing test on an upstream resource makes the downstream resources skip, so bad data doesn't flow on.
How do I run one dbt model and everything downstream of it?+
Put a plus after the name: `dbt run -s "my_model+"` selects the model and all its descendants, where `-s` is the short form of the select flag. A plus before the name selects ancestors, and a number after the plus limits the steps, so `my_model+1` stops at the first-degree descendants.
What does the full refresh flag do in dbt run?+
`dbt run -f` makes dbt treat incremental models as table models, so they are rebuilt from scratch. Use it when an incremental model's schema changes or its logic changes and the whole history must be reprocessed. Snapshots ignore the flag, so their history is kept.
How do I re-run only what failed?+
`dbt retry` re-executes the last invocation from the point of failure, reading `run_results.json`. It needs dbt v1.6 or later. If the failure came before any node ran, such as a connection error, there are no recorded nodes and retry runs nothing.
How do I preview a model without building it?+
`dbt show -s my_model` compiles the model and prints the first 5 rows by default, and the limit flag changes the count. The query runs against the warehouse, but nothing is materialized.
02 / Why practice

The candidate who gets the offer

  1. 01

    Reading a solution is not the same as writing one

    Every engineer who has frozen on a query they had read a dozen times knows the gap. The only preparation that closes it is producing the answer yourself, under time, before the interview does it for you

  2. 02

    76% of hiring managers reject on the coding task, not the resume

    From HackerRank's 2024 Developer Skills Report. Candidates who look strong on paper still fail the live screen if they haven't done timed, executable practice

  3. 03

    5 problem shapes cover 80% of data engineer loops

    Dedup, sessionization, top-N-per-group, slowly-changing dimensions, partition tricks. Writing the shapes by hand turns the unfamiliar into pattern recognition

Related guides