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.
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
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.


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.
Know dbt commands the way the interviewer who asks it knows it.
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 20Flags 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
- 01
dbt init
Creates a new project and the folder structure that the other commands expect.
- 02
dbt debug
Checks the database connection and the project configuration, plus the installed versions, before anything runs.
- 03
dbt deps
Installs the packages listed in packages.yml and writes package-lock.yml, which records the exact versions.
- 04
dbt seed
Loads the CSV reference data that models read through ref.
- 05
dbt build
Builds models in DAG order, running tests and snapshots as it goes. It skips whatever sits downstream of a failure.
- 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?+
What is the difference between dbt run and dbt build?+
How do I run one dbt model and everything downstream of it?+
What does the full refresh flag do in dbt run?+
How do I re-run only what failed?+
How do I preview a model without building it?+
The candidate who gets the offer
- 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
- 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
- 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
dbt interview questions
Questions on dbt models and tests, and on sources
SQL interview questions
The SQL questions asked in data engineering interviews
SQL practice problems
Problems to practice the queries behind dbt models
Data engineer interview prep
How the loop is structured and how to prepare
dbt incremental models
Strategies in dbt Core: merge and unique_key
The data engineering challenge
Dirty, production-shaped data, scored blind each week.