patternpythonMajor
dbt model organization and ref() dependency graph
Viewed 0 times
dbt ref functiondbt model layersdbt dag lineagedbt staging intermediate martsdbt source
Problem
dbt projects without a clear folder convention and consistent ref() usage produce tangled dependency graphs, make lineage impossible to trace, and break when models are renamed or moved.
Solution
Enforce a layered folder structure and always use ref() instead of hardcoded table names:
-- models/staging/stg_orders.sql (clean raw source)
SELECT
id AS order_id,
customer_id,
CAST(created_at AS TIMESTAMP) AS created_at,
status
FROM {{ source('ecommerce', 'raw_orders') }}
-- models/intermediate/int_orders_enriched.sql
SELECT
o.*,
c.country
FROM {{ ref('stg_orders') }} o
JOIN {{ ref('stg_customers') }} c USING (customer_id)
-- models/marts/fct_orders.sql (final business-facing model)
SELECT *
FROM {{ ref('int_orders_enriched') }}
WHERE status = 'completed'
-- models/staging/stg_orders.sql (clean raw source)
SELECT
id AS order_id,
customer_id,
CAST(created_at AS TIMESTAMP) AS created_at,
status
FROM {{ source('ecommerce', 'raw_orders') }}
-- models/intermediate/int_orders_enriched.sql
SELECT
o.*,
c.country
FROM {{ ref('stg_orders') }} o
JOIN {{ ref('stg_customers') }} c USING (customer_id)
-- models/marts/fct_orders.sql (final business-facing model)
SELECT *
FROM {{ ref('int_orders_enriched') }}
WHERE status = 'completed'
Why
ref() tells dbt about dependencies so it builds the DAG correctly, runs models in order, and enables lineage visualization. Hardcoded schema.table references bypass the DAG and cause silent failures when environments differ (dev vs prod schemas).
Gotchas
- Never use direct schema.table references — always ref() for models and source() for raw tables
- Circular dependencies cause dbt to refuse to compile — redesign via intermediate tables
- Staging models should be 1:1 with source tables with only type casts and column renames, no business logic
- dbt run --select +fct_orders rebuilds fct_orders and all its upstream dependencies
Code Snippets
dbt_project.yml materialization defaults by layer
# dbt_project.yml — assign default materializations per folder
models:
my_project:
staging:
+materialized: view
intermediate:
+materialized: ephemeral
marts:
+materialized: tableContext
Structuring a new dbt project or reviewing an existing one for maintainability
Revisions (0)
No revisions yet.