Organize models into three layers. Fight the urge to invent a fourth.

models/
  staging/         # one model per source table; light cleanup only
  intermediate/    # reusable joins, business-logic building blocks
  marts/           # facts, dims, semantic-layer-ready tables

Staging

A staging model is one-to-one with a source table. It renames columns, casts types, coerces nulls. It does not join, aggregate, or filter.

Staging's job is to make every downstream model talk to a clean, consistent shape. Type casts, _loaded_at naming, coalesce on known-null columns — all of it happens here.

Intermediate

An intermediate model composes staging models into reusable building blocks. It exists to be referenced by more than one mart.

A healthy project has maybe a quarter as many intermediate models as marts. If you have an intermediate per mart, your marts are doing too little.

Marts

Marts are what downstream tools read. They are facts (fct_<grain>), dimensions (dim_<entity>), or aggregations.

The fourth-layer temptation

Teams invent a fourth layer when intermediate feels "not quite right". Common names: metrics/, aggregates/, presentation/, semantic/.

Resist. The three layers compose any pipeline you need:

Every extra layer is a new naming convention, a new team debate, and a new onboarding paragraph. The payoff is usually zero.

Mapping onto the medallion architecture

Databricks users will recognize bronze / silver / gold from the medallion pattern. dbt's three layers map onto the medallion layers, but they are not the same thing:

medalliondescribesdbt layerdescribes
BronzeRaw ingested data, as-is(outside dbt)loaded by Auto Loader, DLT, Fivetran
SilverCleaned, deduplicated, type-consistentstaging + intermediatethe shape dbt's DAG imposes
GoldBusiness-ready, aggregatedmartswhat consumers read

Most Causeway teams land bronze outside dbt (it is a data ingestion concern, not a modeling one) and let dbt own silver-to-gold.

Catalog and schema layout

On Unity Catalog, carve environments into catalogs and domains into schemas.

Note

Unity Catalog stitches column-level lineage across dbt runs automatically. A mart that reads two staging views produces two edges in UC lineage without any extra configuration. Resist building a parallel lineage layer.

See also