All posts
6 min read · 2026-04-22

dbt macros that make lineage easier to read

dbt
lineage

Lineage tools work on compiled SQL, so anything you do in macros that hides column references will hide them from lineage too. The opposite is also true: explicit macros make lineage cleaner.

1. Star with exclude, not bare star

dbt_utils.star({{ ref('stg_users') }}, except=['internal_token']) compiles to an explicit column list. Lineage gets per-column edges instead of a single STAR edge.

2. surrogate_key over hand-rolled hashes

Macros like dbt_utils.generate_surrogate_key make the inputs to the hash visible in the compiled SQL, so lineage knows which columns feed the surrogate key.

3. Aliasing in one place

Renaming columns in a single staging layer keeps lineage edges short. Renaming in five different marts produces five distinct lineage chains for the same logical column.

4. Avoid select-from-select-from-CTE chains

Three CTEs that just rename columns add three edges to every lineage chain. Collapse them when they're doing nothing useful.

5. Document overrides in the SQL, not the YAML

If you intentionally hardcode a column, leave a SQL comment. Lineage tools cannot read your YAML.

Try it on your own SQL: