Skip to content

dbt project best practices

Teams searching for dbt project best practices usually want a structure that is easy to scale, review, and maintain. dbt-forge helps by scaffolding a consistent starting point and enforcing project health checks with doctor.

A maintainable dbt project should separate staging, intermediate, and marts so the purpose of each model is obvious. That is the default structure in dbt-forge.

Use Project structure to review the generated layout, then adapt it carefully rather than mixing every model into one directory.

The scaffold uses prefixes like stg_ and int_ to make layer boundaries visible. That improves review speed and reduces naming collisions as the project grows.

Run doctor regularly to validate naming conventions and other rules that drift over time.

3. Pin packages and manage dependencies explicitly

Section titled “3. Pin packages and manage dependencies explicitly”

A dbt project template should define packages intentionally instead of inheriting them from an older repository. dbt-forge generates packages.yml with pinned version ranges and keeps the result updateable through update.

Do not treat tests and documentation as a later cleanup step. Teams move faster when:

  • source YAML is present
  • schema tests are added with the model
  • descriptions are written alongside the SQL
  • health checks run before pull requests are merged

Use add to generate tests and supporting files. Use docs generate when you want AI-assisted descriptions for existing models and columns.

SQLFluff catches SQL style issues. dbt-forge lint catches architectural problems: fan-out hotspots, marts referencing sources directly, complex models that should be split, and YAML-SQL column drift. Run it alongside doctor:

Terminal window
dbt-forge lint --ci
dbt-forge doctor --ci

Use lint for the full rule list and configuration.

Use impact to see which downstream models are affected when you change an upstream model. Add the --pr flag to generate markdown for pull request descriptions:

Terminal window
dbt-forge impact --diff --pr

7. Enforce data contracts on public models

Section titled “7. Enforce data contracts on public models”

Public models in a dbt Mesh need contract: { enforced: true } with explicit column types. Use contracts generate to create them from warehouse metadata instead of writing YAML by hand.

Use changelog generate to detect column removals, type changes, and model deletions between git refs. Share the output with downstream consumers before they discover changes in production.

The fastest way to lose consistency is to scaffold well once and never check again. Use these commands as part of the normal workflow:

Terminal window
dbt-forge doctor
dbt-forge status
dbt-forge cost --days 7

This gives teams a repeatable way to review structure, coverage, freshness, cost, and project health.

10. Prefer generated standards over manual copy-paste

Section titled “10. Prefer generated standards over manual copy-paste”

Copying files from older dbt projects tends to import stale CI config, warehouse assumptions, and inconsistent ownership. Start from a clean scaffold with How to scaffold a dbt project or compare against dbt project template.

  • Use Getting started if you want the quickest path from install to a valid project.
  • Read init for the project generation options.
  • Use dbt Mesh project setup when best practices need to extend across multiple dbt projects.