Home / Data Platform / dbt & Quality

Data PlatformCheat sheetIntermediate

Advisory: structuring dbt projects - layers, naming, one project or many, and ownership

A dbt project that grows without structure becomes slow to build and hard to change. Use clear staging, intermediate and mart layers with naming rules, decide between a monolith and several projects with cross-project references, set ownership and access per group, and keep CI and environments consistent.

Deepak Bhardwaj3 min read

Applies todbt Core and dbt Cloud on Snowflake, Databricks, BigQuery, Fabric, Redshift, Postgres

Layers and naming

Layer Folder Prefix Purpose Materialization
Sources models/staging/<source> stg_<source>__<entity> 1:1 with source tables; rename, cast, light cleaning View
Intermediate models/intermediate/<domain> int_<entity>_<verb> Reusable joins and logic Ephemeral/view/table
Marts models/marts/<domain> fct_, dim_ Business-facing facts and dimensions Table/incremental

Rules that help:

  • Only staging models read source(). Everything else uses ref().
  • Marts don't reference other marts' internals; share via intermediate models.
  • One YAML file per folder for docs and tests.

One project or many?

Monolith Multiple projects (mesh)
Simple, one DAG, easy refactoring Domain teams own and deploy independently
Builds and CI slow as it grows Cross-project ref needs public models and versioning
Fine for one team, hundreds of models Fits several teams, thousands of models

A common path: start as a monolith, split by domain once teams step on each other or CI takes too long.

Ownership and access

# groups and access in dbt
groups:
  - name: finance
    owner:
      name: Finance Data Team
      email: finance-data@example.com

models:
  - name: fct_revenue
    config:
      group: finance
      access: public        # other groups/projects may ref it
      contract:
        enforced: true
  - name: int_revenue_adjustments
    config:
      group: finance
      access: private       # only finance models may ref it

Public models get contracts and versions, so consumers aren't broken by refactoring (see the data contracts post).

Environments and CI

Item Recommendation
Targets dev (per developer schema), ci, prod
CI Slim CI: build only modified models and their children with state comparison
Prod deploy From main branch only, by a service identity
Style SQL linting (e.g. SQLFluff) and pre-commit checks
Docs Generated on each prod deploy

Performance hygiene

  • Make large facts incremental with a lookback window.
  • Avoid deep chains of views over big tables. Materialize a table at sensible points.
  • Tag models by schedule (hourly, daily) and run with selectors rather than everything every time.

Tip

Write the conventions down in the repo (CONTRIBUTING.md) and enforce what you can with linting and CI checks. Conventions that only live in people's heads disappear when the team changes.

Checklist

  • Layer folders and naming documented
  • Source access restricted to staging
  • Monolith vs multi-project decided
  • Groups, owners and access levels set
  • Public models contracted and versioned
  • Slim CI, linting and environment targets in place