Table of Content
Subscribe to our Newsletter
Get the latest from our team delivered to your inbox
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Ready to get started?
Try It Free
A breaking change in a data pipeline rarely announces itself. A renamed column in a Postgres table, a dropped field in an upstream API response, a dbt model that changes its grain, a Spark job that silently starts null filling a column it used to populate. None of these throw an error at deploy time. They surface hours or days later as a broken dashboard, a failed ML feature, or a support ticket, by which point the root cause is buried under every commit made since. Catching these changes before they ship means analyzing the dependency graph at the code level, before the pull request merges, not waiting for a downstream symptom to trigger an investigation. This post walks through where breaking changes actually originate, what it takes to catch them pre merge, and how that changes the cost of a schema change from an incident to a code review comment.
Breaking changes rarely start in SQL. They start in the code that produces the SQL: a Python transformation that reshapes a dataframe, an ORM model in Java or Python that changes how an application writes to its database, a dbt model whose grain shifts after a join is added, or a Spark job whose schema drifts after a library upgrade. By the time a query runs against the resulting table, the change is already baked in. Catching it there means the incident has already started. Catching it in the code that produced the change, before the pull request merges, is what actually prevents it.
A useful pre merge check needs visibility into more than the file being changed. It needs the full downstream dependency graph, built from actual code analysis rather than a static schema snapshot, covering the languages and layers a given team actually uses.
| Layer | What breaks here |
|---|---|
| SQL and dbt models | Renamed or dropped columns, changed grain, altered join keys |
| Python and Spark pipelines | Reshaped dataframes, silent type coercion, dropped fields in a transformation step |
| ORM layers (Java, Python) | Application level schema changes that never touch a migration script reviewed by the data team |
| AI and feature pipelines | A feature definition change that silently alters what a model is trained or served on |
Without coverage across all four, a pre merge check only catches the changes that happen to route through SQL, which in most engineering organizations is a shrinking share of where pipeline logic actually lives.
Foundational, a data and AI governance platform, analyzes pipeline source code directly rather than relying on query logs or a static catalog snapshot, so a schema or logic change is checked against its actual downstream impact at the pull request stage, across SQL, Python, Spark, and ORM layers alike. At Lightricks, this kind of pre merge analysis prevents roughly 100 issues each month across more than 150 pull requests, according to Eyal El-Bahar, VP of BI and Analytics. At Vio, a similar approach cut potential issues by 52 percent and reduced cycle time by 37.5 percent.
Catching a breaking change before it ships requires analyzing the downstream dependency graph at the code level, covering SQL, Python, Spark, and ORM layers, and running that check at the pull request stage rather than after deployment. That requires source code analysis rather than query log parsing, since many breaking changes originate in pipeline or application code that never appears in a query log.
Most breaking changes originate outside SQL: a Python transformation that reshapes a dataframe, an ORM model change in the application layer, or a Spark job whose schema drifts after a dependency upgrade. By the time the resulting change reaches a warehouse query, the root cause is already several steps removed.
dbt tests catch violations of rules you have already defined for models you have already written. They do not catch a breaking change introduced upstream in a Python pipeline or an application's ORM layer, since those changes happen outside dbt's model graph entirely.
A breaking change caught in code review costs a comment and a fix before merge. The same change caught in production costs an incident: a broken dashboard, a corrupted downstream table, or a support escalation, plus the time spent tracing the root cause back through every commit made since the change shipped.
Catching breaking changes before they ship is a prevention problem, not a monitoring problem, and it depends on visibility into the pipeline and application code where most of these changes actually originate. See how this fits into a broader data incident prevention strategy, or explore Foundational's approach to data governance end to end.
See how source code analysis flags pipeline breaking changes at the pull request.
See how source code analysis flags pipeline breaking changes at the pull request.
See how source code analysis flags pipeline breaking changes at the pull request.