Auto Draft Schema Change Impact Analysis From Lineage
For Data Engineers ·
What This Builds
A schema change that looks safe in isolation can quietly break three downstream dashboards nobody remembered were built on that column. This workflow scans your dbt lineage graph for the model being changed, drafts a "who's affected" summary with an AI step, and posts it to the relevant Slack channels before the migration ships. It reads the lineage graph so nobody has to manually trace dependencies by hand before a risky change, which is the step that gets skipped when a deadline is tight.
Prerequisites
- Comfortable reading a dbt lineage graph (
dbt docs generate/ the DAG view) and understanding upstream/downstream model relationships - A place to run n8n: self-hosted (free, self-managed) or n8n's cloud plans (check n8n's pricing page for current tiers)
- A Claude or equivalent API key for the drafting step, billed per token with a spend cap you set
- Read access to your dbt project's
manifest.json(generated bydbt docs generateordbt compile), which contains the full lineage graph as structured data - Total ongoing cost: n8n hosting plus metered API usage, which stays low since this triggers only when a schema change PR is opened, not continuously
The Concept
Your dbt lineage graph already knows every model downstream of the one you are about to change. What it does not do on its own is turn that list of model names into a plain-language note explaining who gets affected and how. This workflow bridges that gap: it reads the graph, hands the list of downstream models to an AI step along with a bit of context about what is changing, and gets back a summary a stakeholder who has never opened dbt docs can still understand.
Build It Step by Step
Part 1: Trigger on a schema change
- In n8n, start with a Webhook node that your CI pipeline calls when a PR touches a model's schema (a column rename, drop, or type change), or a GitHub Trigger node watching for PRs that modify files under your
models/directory. - Add a node to parse which model file(s) changed and what specifically changed (this can be a simple diff parse, or you can pass the raw diff to the AI step in Part 2 and let it identify the change type).
Part 2: Read the lineage graph
- Add a node to fetch your project's
manifest.json(from your dbt Cloud API, a CI artifact, or a scheduled export to cloud storage that this workflow reads from). - Add a Code node (n8n supports a JavaScript function node) that parses the manifest's
child_mapordepends_onrelationships to build a list of every model downstream of the one being changed, including how many levels away each one is. - Cross-reference that list against any exposures defined in your dbt project (dashboards, reports registered as
exposuresin dbt), if you use that feature, since those are the ones a stakeholder actually cares about.
Part 3: Draft and post the impact note
- Add an AI node calling Claude with this prompt:
You are drafting a schema change impact note for a data engineering team. You will receive: the name of the model being changed, a description of the change (column renamed, dropped, or type changed), and a list of downstream models and exposures that depend on it, with their distance from the changed model. Write a short note with three parts: What's Changing (1-2 sentences, plain language), Who's Affected (bulleted list of downstream models/dashboards, grouped by how directly they depend on the change), Suggested Action (1-2 sentences on what the model owners should check before this ships). Only list dependencies that were provided to you. Do not guess at dependencies that were not in the input.
- Add a Slack node that posts the drafted note to the channel(s) owning the affected downstream models. If your team tags model owners by Slack handle in a metadata file, map that into the message so the right people get pinged instead of a general channel getting noise.
- Add the note as a comment on the originating PR too (via a GitHub node), so the context lives next to the code change, not just in a Slack thread that scrolls away.
Real Example: Renaming a shared order_status column
Setup: A PR renames order_status to fulfillment_status in the stg_orders model. The webhook fires, pulls the manifest, and finds 4 downstream models and 2 dbt exposures depending on stg_orders.
Input: Change description ("column renamed"), downstream list: int_orders_enriched (1 level away), fct_orders (2 levels away), rpt_daily_fulfillment (3 levels away, tagged as a Looker exposure), and rpt_customer_orders (3 levels away).
Output: A Slack note in #data-eng-changes: What's Changing explains the rename in plain language, Who's Affected lists the two exposures first since those are stakeholder-facing, Suggested Action recommends confirming the Looker dashboard's field mapping gets updated before the migration merges, not after.
Time saved: Replaces 20 to 30 minutes of manually clicking through the dbt docs DAG (easy to miss a third-level dependency) with a note that is ready the moment the PR opens.
What to Do When It Breaks
- Manifest is stale, so the lineage list misses a real downstream model → The manifest only reflects the last time
dbt docs generateordbt compileran. If your project regenerates it nightly rather than on every commit, the impact note can miss same-day additions. Regenerate it as part of the same CI run that triggers this workflow, not on a separate nightly schedule. - Webhook stops firing on new PRs and nobody notices because impact notes were never load-bearing enough to be missed at a glance → This is the quiet failure mode. Add an n8n error workflow that alerts a Slack channel on any failed execution, and periodically open a real PR that touches a model with known dependents to confirm the note still shows up.
- Impact note lists a dependency that does not actually exist anymore → The manifest can lag behind if a model was recently deprecated but its lineage entry was not cleaned up. Treat the note as a starting point for review, not a guarantee, and spot-check the first several notes against the live dbt docs DAG before trusting it fully.
- Note goes to the wrong Slack channel or misses the actual model owner → Check your owner-mapping metadata is current. Ownership drifts as people change teams, and a note that pings someone who left the team six months ago trains people to ignore it.
Variations
- Simpler version: Skip the AI drafting step and just post the raw list of downstream models and exposures to Slack. Less readable, zero risk of a misworded summary, still better than nothing.
- Extended version: Add a gate that blocks the PR from merging until someone reacts to the Slack note, for changes touching a model with exposures.
What to Do Next
- This week: Run it against a schema change you already know the blast radius of, and check whether the drafted note matches what you know to be true.
- This month: Add exposure ownership metadata to your dbt project if you do not have it yet, since the note is only as useful as the owner mapping behind it.
- Advanced: Pair this with the "Chain a New Data Source Onboarding Workflow" build so newly onboarded sources get exposure metadata from day one, instead of showing up as an unlabeled dependency in a future impact note.
Advanced guide for Data Engineer professionals. These techniques use more sophisticated AI features that may require paid subscriptions.