dbt run Command: Executing Models and Understanding Its Output
dbt run is the command most people learn first and use most often, but the details of what it actually does โ and doesnโt do โ matter more than they seem to at first glance. Itโs easy to assume dbt run validates your data too; it doesnโt. Understanding exactly where its responsibility ends is what keeps you from mistaking โthe run succeededโ for โthe data is correct.โ
What dbt run Actually Does
dbt run compiles every modelโs SQL (resolving ref(), source(), and Jinja), determines the correct execution order from the DAG, and executes each model against your warehouse โ creating tables or views depending on each modelโs configured materialization.
dbt runCritically, it does not run tests. A dbt run that completes with zero errors tells you the SQL executed without a database error โ it says nothing about whether the resulting data is actually correct. Thatโs what dbt test and dbt build are for, covered in dbt Tests and dbt build.
Reading the Output
Running with dbt=1.8.0Found 42 models, 118 tests, 3 seeds, 2 snapshots
1 of 42 START sql table model staging.stg_orders ....... [RUN]1 of 42 OK created sql table model staging.stg_orders ... [SELECT 48213 in 1.2s]2 of 42 START sql view model staging.stg_customers ...... [RUN]2 of 42 OK created sql view model staging.stg_customers .. [CREATE VIEW in 0.3s]...Completed successfully
Done. PASS=42 WARN=0 ERROR=0 SKIP=0 TOTAL=42Each line tells you the model, its materialization type, and how long it took โ the timing is often the first clue when a model that used to run in seconds suddenly takes minutes, usually pointing to a data volume change or a missing incremental filter.
Selecting a Subset of Models
Running the entire project on every change wastes both time and warehouse compute. Selection syntax lets you scope a run to exactly whatโs relevant.
# A single modeldbt run --select stg_orders
# A model and everything downstream of itdbt run --select stg_orders+
# A model and everything it depends ondbt run --select +sales_summary
# An entire folderdbt run --select staging.*
# Models tagged a specific way (covered in dbt Tags)dbt run --select tag:financeThis selection syntax is the same graph-based syntax introduced in Data Lineage (DAG) โ itโs not a separate feature, but a direct expression of the dependency graph dbt already maintains.
Full Refresh
Incremental models, by default, only process new or changed rows on subsequent runs. --full-refresh forces a complete rebuild from scratch โ dropping and recreating the table rather than appending or merging.
dbt run --select daily_revenue --full-refreshThis is the fix for a specific and common problem: an incremental modelโs logic changed in a way that the existing incrementally-built table doesnโt reflect (a new column, a changed calculation) โ a full refresh rebuilds the table with the corrected logic applied to all historical data, not just new rows going forward.
Running Against a Specific Target
Most projects define multiple targets in profiles.yml โ dev, staging, prod โ and dbt run accepts a --target flag to choose which one a specific invocation uses.
dbt run --target prodWithout an explicit --target, dbt uses whatever profiles.yml marks as the default target, which is why CI/CD pipelines should always be explicit about which target theyโre running against rather than relying on a possibly-changed default.
Threads: Controlling Parallelism
dbt runs independent models (ones without a dependency relationship between them) concurrently, controlled by the threads setting.
dbt run --threads 8More threads generally means faster runs on projects with many independent model branches, up to the point where your warehouseโs concurrency limits or connection pool become the bottleneck instead โ thereโs a real ceiling past which more threads stop helping and start causing connection contention errors.
Common Failure Patterns and What They Mean
Database Error in model stg_orders (models/staging/stg_orders.sql) Object 'RAW_APP_DATA.ORDERS' does not exist or not authorizedThis is almost always a source() configuration issue โ the schema or database name in sources.yml doesnโt match reality, or the running role lacks permission on the underlying table.
Compilation Error in model customer_orders (models/core/customer_orders.sql) 'stg_custmers' is undefinedA ref() typo, caught before any SQL executes โ covered in more depth in ref() Function.
dbt run vs dbt build
dbt run only builds models โ it skips tests, seeds, and snapshots entirely. If your workflow needs all of those interleaved in proper dependency order, dbt build (covered next) is almost always the better default for a scheduled production job; dbt run alone is better suited to fast local iteration when youโre deliberately not re-testing yet.
Common Mistakes
Assuming a successful dbt run means correct data. It only means the SQL executed without a database error โ always follow with dbt test or use dbt build instead.
Running the full project on every local iteration. Scoping with --select during development saves significant time and avoids unnecessarily rebuilding unrelated parts of a large project.
Forgetting --full-refresh after changing incremental logic. Without it, an incremental modelโs historical data can remain built with outdated logic indefinitely.
Summary
| Flag | Purpose |
|---|---|
--select | Scopes the run to specific models or graph selections |
--full-refresh | Forces incremental models to rebuild completely |
--target | Chooses which warehouse/environment connection to use |
--threads | Controls how many models run concurrently |
dbt run is the workhorse command, but its scope is narrower than it feels โ it builds, it doesnโt validate. Pairing it with dbt test, or replacing both with dbt build, is what actually closes the loop between โthe pipeline ranโ and โthe data is trustworthy.โ