Loading...
Loading...
Safely refactors dbt models with downstream impact analysis. Use when restructuring dbt models for: (1) Task mentions "refactor", "restructure", "extract", "split", "break into", or "reorganize" (2) Extracting CTEs to intermediate models or creating macros (3) Modifying model logic that has downstream consumers (4) Renaming columns, changing types, or reorganizing model dependencies Analyzes all downstream dependencies BEFORE making changes.
npx skill4agent add altimateai/data-engineering-skills refactoring-dbt-modelscat models/<path>/<model_name>.sql# Get full dependency tree (model and all its children)
dbt ls --select model_name+ --output list
# Find all models referencing this one
grep -r "ref('model_name')" models/ --include="*.sql"# For each downstream model, check what columns it uses
cat models/<path>/<downstream_model>.sql | grep -E "model_name\.\w+|alias\.\w+"| Opportunity | Strategy |
|---|---|
| Long CTE | Extract to intermediate model |
| Repeated logic | Create macro in |
| Complex join | Split into intermediate models |
| Multiple concerns | Separate into focused models |
-- orders.sql (200 lines)
with customer_metrics as (
-- 50 lines of complex logic
),
order_enriched as (
select ...
from orders
join customer_metrics on ...
)
select * from order_enriched-- customer_metrics.sql (new file)
select
customer_id,
-- complex logic here
from {{ ref('customers') }}
-- orders.sql (simplified)
with order_enriched as (
select ...
from {{ ref('raw_orders') }} orders
join {{ ref('customer_metrics') }} cm on ...
)
select * from order_enrichedcase
when amount < 0 then 'refund'
when amount = 0 then 'zero'
else 'positive'
end as amount_category-- macros/categorize_amount.sql
{% macro categorize_amount(column_name) %}
case
when {{ column_name }} < 0 then 'refund'
when {{ column_name }} = 0 then 'zero'
else 'positive'
end
{% endmacro %}
-- In models:
{{ categorize_amount('amount') }} as amount_category# Compile to check syntax
dbt compile --select +model_name+
# Build entire lineage
dbt build --select +model_name+
# Check row counts (manual)
# Before: Record expected counts
# After: Verify counts match# Compare row counts before and after
dbt show --inline "select count(*) from {{ ref('model_name') }}"
# Spot check key values
dbt show --select <model_name> --limit 10| Symptom | Refactoring |
|---|---|
| Model > 200 lines | Extract CTEs to models |
| Same logic in 3+ models | Extract to macro |
| 5+ joins in one model | Create intermediate models |
| Hard to understand | Add CTEs with clear names |
| Slow performance | Split to allow parallelization |