Data Engineering  /  dbt

🔄 dbt — Data Build Tool Guide 1 of 8 60 guides · updated 2026

Analytics engineering with SQL — models, tests, sources, and Jinja macros that turn raw warehouse tables into trustworthy, documented data products.

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.

Terminal window
dbt run

Critically, 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.0
Found 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=42

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

Terminal window
# A single model
dbt run --select stg_orders
# A model and everything downstream of it
dbt run --select stg_orders+
# A model and everything it depends on
dbt run --select +sales_summary
# An entire folder
dbt run --select staging.*
# Models tagged a specific way (covered in dbt Tags)
dbt run --select tag:finance

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

Terminal window
dbt run --select daily_revenue --full-refresh

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

Terminal window
dbt run --target prod

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

Terminal window
dbt run --threads 8

More 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 authorized

This 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 undefined

A 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

FlagPurpose
--selectScopes the run to specific models or graph selections
--full-refreshForces incremental models to rebuild completely
--targetChooses which warehouse/environment connection to use
--threadsControls 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.”