dbt

dbt build in Practice: Run, Test, and Snapshot Safely in One Command

2026-04-19
NicheeLab Editorial Team

dbt build constructs models, seeds, and snapshots, then runs tests against the result in dependency order. Compared to running dbt run, dbt test, and dbt snapshot separately, it is harder to break the pipeline and easier to wire into CI.

This article assumes stable features from the official dbt documentation and walks through the comparisons most often asked on the Analytics Engineer exam (run/test/snapshot vs. build, selectors, state/defer) from a practitioner's perspective.

What dbt build Does and Why It Helps

dbt build constructs the selected resources (models, seeds, snapshots) along the DAG and then runs tests (generic and singular) once they are built. Tests whose dependencies are not satisfied are skipped automatically, and tests attached to failed upstream nodes do not run either.

The key benefits are ordering and atomicity. A single command runs build → validate end-to-end, preventing the ordering mistakes and missed steps you get from individual commands. Making dbt build the default CI entry point keeps operations stable.

  • What is included: models, seeds, snapshots, and tests (tests run last)
  • Parallel execution based on the DAG. Nodes with unresolved dependencies wait; failed branches skip downstream work
  • More consistent results than separate dbt run/test/snapshot (tests run against the built result)
  • CI/CD default: pick dbt build first, then narrow scope with selectors as needed
CommandMain target / roleWhat it doesRole inside dbt build
dbt runmodels (materialization)Runs model SQL to update tables, views, and incremental modelsRuns inside build (before tests)
dbt testgeneric/singular testsValidates data quality with unique, not_null, and function-based testsRuns together at the end of build
dbt snapshotsnapshotsUpdates snapshot tables used for SCDsRuns inside build (before tests)
dbt seedseeds (CSV loads)Loads CSV files into the target databaseRuns inside build (before tests)
dbt buildAll of the above combinedBuilds in DAG order → tests against the resultThe focus of this article. A good CI default

Conceptual flow of dbt build

seedsmodelstestssnapshots(independent / source-derived)

Minimal example

dbt build
# profiles.yml と dbt_project.yml が設定済みであれば、この1行で
# models/seeds/snapshots を構築し、最後に tests を実行します。

Execution Order and Dependency Behavior

dbt build resolves the DAG of selected nodes and builds models, seeds, and snapshots first. Tests always run after that, and only when their parent node (target table/view/snapshot/seed) succeeded. Ephemeral models are not materialized; they are inlined into the parent query.

Incremental models update incrementally by default, or rebuild from scratch when --full-refresh is set. Tests run against the post-update state, so quality checks always evaluate the latest build output.

  • Tests run after resources are built (tests with failed or unbuilt parents are skipped)
  • Ephemeral models are not built (they are inlined into the parent)
  • --full-refresh typically applies only to incremental models (snapshots keep their normal incremental behavior)
  • Seeds are loaded before any models that depend on them

Order-aware baseline (no extra flags)

dbt build
# DAG に基づいて seeds/models/snapshots → tests の順で動く

Targeting run/test/snapshot with Selectors

dbt build supports flexible scoping with --select and --exclude. You can target by tag, file path, model name, or resource type (model:, snapshot:, seed:, test:), and state selectors like state:modified are also available. Append + for descendants, prefix + for ancestors.

In larger repos, combining tags, paths, and resource types to minimize scope is the most effective way to cut CI runtimes.

  • Type selectors: model:my_model, snapshot:, seed:, test:
  • Tag selectors: tag:core, tag:critical
  • Path selectors: path:models/marts/
  • State selectors: state:modified, state:new
  • Graph operators: +my_model (ancestors), my_model+ (descendants), +my_model+ (both)

Common selector patterns

# 重要タグのモデルとその子孫だけを構築し、最後に tests
dbt build --select tag:critical+

# スナップショットだけを更新し、関連 tests のみ実行
dbt build --select snapshot:

# マート配下と依存元(祖先)を含めて構築
dbt build --select +path:models/marts/

# 変更点とその下流のみ(state ディレクトリの指定は別途)
dbt build --select state:modified+ --state target/

Concurrency, Fail-Fast, and Skip Behavior

dbt build runs independent nodes in parallel based on the configured thread count. When a node fails, its downstream nodes and the tests tied to them are skipped. With --fail-fast, the entire run stops at the first failure.

For DAGs with many branches, tune --threads to compress total runtime, and use --fail-fast for critical validation paths so failures surface as early as possible.

  • Control parallelism via threads in profiles.yml or the --threads flag
  • Everything downstream of a failed node is skipped (tests included)
  • --fail-fast stops at the first failure (useful for fast CI feedback)
  • On retry, scope down to the problem area with selectors (e.g. model:orders+ or tag:data_quality)

Parallelism and early failure

# 8 並列で実行し、最初の失敗で停止
dbt build --threads 8 --fail-fast

Incremental Builds for CI/PRs: Combining state and defer

The standard incremental-build pattern is to point --state at production artifacts (such as manifest.json) and select only the changed nodes and their downstream with --select state:modified+. Adding --defer lets unselected upstream refs fall back to production-built objects, keeping CI work to a minimum.

This combination dramatically cuts per-PR validation time. Have the production job emit its artifacts each run, and wire the CI pipeline to read them.

  • state:modified picks changed nodes based on diffs in code and compiled output
  • Append + to also include the downstream of changed nodes (impact validation)
  • --defer routes unselected refs to artifacts at the --state location (depends on production)
  • For PRs, stick to dbt build and avoid full refreshes

A typical CI command

# プロダクションのアーティファクトを参照し、変更点とその下流のみを検証
# artifacts/ に本番の manifest.json 等がある前提
dbt build --select state:modified+ --state artifacts/ --defer

Pitfalls and Best Practices

dbt build is powerful, but mixing in full refreshes of incremental models or large batches of snapshots without thought inflates both runtime and cost. Lean on diffs and tests in CI, and separate schedules and workloads in production.

For data quality, use severity:error on critical tests and severity:warn on supporting ones, and enable store_failures to collect failing rows. That makes the improvement cycle much smoother.

  • Default to dbt build in CI. Keep separate run/test calls to a minimum
  • Use --full-refresh deliberately. Avoid it in PRs and CI as a rule
  • Curate test granularity and severity. Cover unique/not_null on critical key constraints at minimum
  • Run large snapshots in dedicated time windows and parallelize tests on separate branches
  • Maintain clean tags and paths so selectors can target precisely

Schema test config example (collect failures)

version: 2
models:
  - name: orders
    columns:
      - name: id
        tests:
          - unique:
              severity: error
              store_failures: true
          - not_null:
              severity: error

Check Your Understanding

Analytics Engineer

問題 1

As an Analytics Engineer, you need to speed up PR validation. You want to reference the production artifacts (manifest.json) and build/validate only the changed models and their downstream. Which command is the most appropriate?

  1. dbt build --select state:modified+ --state artifacts/ --defer
  2. dbt run && dbt test --select state:modified+
  3. dbt build --select tag:modified --fail-fast
  4. dbt snapshot --select state:modified --defer

正解: A

The canonical approach is state:modified+ to select changed nodes and their downstream, --state to reference the production artifacts, and --defer to route unselected upstream refs to the production-built objects. B splits run/test, which risks ordering mistakes and missed selections. C uses tag:modified, which is not what you want. D runs only snapshot, not build.

Frequently Asked Questions

Does dbt build also run exposures and source freshness?

No. dbt build only targets models, seeds, snapshots, and tests. Exposures are metadata, and source freshness is run separately with dbt source freshness.

What is the difference between dbt build and running dbt run then dbt test separately?

build follows the DAG to construct resources and always runs tests against the result at the end. Running them separately is prone to ordering and selection mismatches, so dbt build is the safer choice in CI.

Jobs that include snapshots are getting heavy. How should I handle that?

Separate snapshots by tag or path so you can split scheduled batches from PR validation. For PRs, run only diffs using state:modified+ with --defer, and leave large snapshots to the production schedule.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
dbt

dbt Models: SQL-Defined Transformation Units (2026)

Model fundamentals — SELECT-based definitions, naming, refs,...

dbt

dbt Analytics Engineering Exam: Complete Guide (2026)

Pass the AE Certification — scope, weighting, sample questio...

dbt

dbt Cloud vs dbt Core: Feature & Cost Comparison (2026)

Honest comparison of dbt Cloud vs. dbt Core — IDE, scheduler...

dbt

dbt Project Structure: models/seeds/macros Layout (2026)

Recommended dbt project layout — models, seeds, macros, snap...

dbt

dbt_project.yml Explained: Every Config (2026)

Every dbt_project.yml setting that matters — paths, vars, ma...

Browse all dbt articles (101)
© 2026 NicheeLab All rights reserved.