When data quality issues emerge, the clock is ticking. Business decisions are being made on bad data, reports are showing incorrect numbers, and stakeholders are losing trust. Root cause analysis using data lineage helps you trace problems upstream to their source—fast.
"We discovered our revenue was underreported by $2.3M. It took us two weeks to find the root cause: a silent truncation in a string-to-number conversion five steps upstream." — Finance Director
Without lineage, troubleshooting data issues is like debugging with no stack trace. You know something's wrong, but you have to manually investigate every transformation, join, and filter until you find the culprit.
Clearly define what's wrong:
Issue Detected:
Table: analytics.monthly_revenue
Column: total_revenue
Problem: Values 30% lower than expected
Timeframe: Started December 19, 2025
Affected Records: All records since that date
Get the full lineage path back to sources:
-- Get upstream lineage for the affected asset
WITH RECURSIVE lineage_path AS (
SELECT
table_name,
column_name,
upstream_table,
upstream_column,
transformation_logic,
1 as depth
FROM lineage_metadata
WHERE table_name = 'analytics.monthly_revenue'
AND column_name = 'total_revenue'
UNION ALL
SELECT
l.table_name,
l.column_name,
l.upstream_table,
l.upstream_column,
l.transformation_logic,
lp.depth + 1
FROM lineage_metadata l
JOIN lineage_path lp
ON l.table_name = lp.upstream_table
WHERE lp.depth < 10
)
SELECT * FROM lineage_path
ORDER BY depth DESC;
Start in the middle of the lineage path and work backward:
Lineage Chain (depth 5 to depth 1):
✓ analytics.monthly_revenue [ISSUE HERE]
? staging.aggregated_sales [TEST THIS]
? staging.cleaned_transactions
? staging.raw_transactions
? external.payment_api
Testing staging.aggregated_sales:
SELECT SUM(revenue) FROM staging.aggregated_sales
WHERE date >= '2025-12-19';
Result: Values look correct here
Conclusion: Issue is in analytics.monthly_revenue generation
Testing transformation logic:
Found: Filter condition added on Dec 19
WHERE transaction_status = 'completed'
Root Cause Found:
New filter excludes 'pending' transactions
Pending transactions are ~30% of volume
This matches the observed discrepancy!
Confirm your hypothesis:
Use forward lineage to find what else is affected:
Downstream Impact:
⚠ dashboards.executive_summary (incorrect revenue)
⚠ reports.board_presentation (wrong numbers)
⚠ ml_models.revenue_forecast (trained on bad data)
⚠ finance.quarterly_report (compliance risk!)
Symptom: Unexpectedly short strings or rounded numbers
Cause: Data type mismatch in transformation
Lineage Search: Look for type conversions (VARCHAR(50) → VARCHAR(20))
Symptom: Row counts lower than expected
Cause: Overly restrictive filter or failed join
Lineage Search: Check WHERE clauses and JOIN conditions
Symptom: Row counts higher than expected
Cause: Missing DISTINCT or bad join
Lineage Search: Look for many-to-many joins
Symptom: Data hasn't updated recently
Cause: Upstream pipeline failure
Lineage Search: Check job execution timestamps
Symptom: Totals don't match expected values
Cause: Incorrect GROUP BY or SUM logic
Lineage Search: Trace aggregation transformations
import wia_lineage
# Detect anomaly
anomaly = {
'table': 'analytics.monthly_revenue',
'column': 'total_revenue',
'expected': 1000000,
'actual': 700000,
'date': '2025-12-19'
}
# Run automated root cause analysis
rca = wia_lineage.analyze_root_cause(anomaly)
# Results:
print(rca.summary())
"""
Root Cause Analysis Results:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Confidence: 87%
Root Cause: Filter condition change
Location: etl/monthly_revenue.sql:45
Changed: 2025-12-19 08:34:12
Changed By: john.doe@company.com
Git Commit: abc123
Recommendation:
Remove WHERE transaction_status = 'completed'
OR include 'pending' transactions in revenue
Estimated fix time: 15 minutes
Backfill required: Yes (19 days)
"""
Combine automated data quality monitoring with lineage:
# Data quality test
assert daily_revenue > 0.8 * expected_revenue
# On failure:
if test_failed:
lineage = get_upstream_lineage('analytics.daily_revenue')
for node in lineage:
run_validation(node)
if node.validation_failed:
alert(f"Root cause found: {node}")
break
Include lineage in alerts:
ALERT: Revenue data quality issue
Table: analytics.monthly_revenue
Issue: 30% lower than baseline
Started: 2025-12-19
Lineage Path:
analytics.monthly_revenue
← staging.aggregated_sales
← staging.cleaned_transactions
← staging.raw_transactions ⚠ SUSPECT
← external.payment_api
Recommended Action:
Investigate staging.raw_transactions
Check for filter/join changes on 2025-12-19
Problem: Customer churn predictions suddenly became unreliable (accuracy dropped from 87% to 62%)
Traditional Investigation: Would take weeks, checking training data, features, model code, etc.
Lineage-Powered RCA: