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 usesref(). - 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