sql.sbEnglish resources

Data warehouse · lineage

Data lineage vs task dependency: why the two graphs differ

A scheduler graph answers “which job waits for which job”. A data lineage graph answers “which data produces which data”. They describe the same pipeline, but they are not the same graph — and when they disagree, impact analysis gives different answers.

Quick answer

Task dependency is declared execution order; data lineage is the actual data derivation. A dependency can exist without data flow (a job waits for a signal), and data flow can exist without a declared dependency (a view reads a table no job declares). Use lineage to know what data is affected, and dependencies to know what to re-trigger.

One workflow, two graphs

The example below has three jobs and one view. JOB_A loadsstg_orders, JOB_REPORT writes report_daily fromv_customer_orders, and the view also reads customers — a table loaded by another team. Walk the scenarios and watch what each graph can and cannot see.

One workflow · two graphs

Pick a scenario and compare what the scheduler graph and the data lineage graph each reveal.

Baseline: How does the workflow look before anything goes wrong?

Scheduler / task dependencyWho waits for whom
JOB_Aloads stg_orders from raw_orders
depends_on (declared)
JOB_REPORTwrites report_daily from v_customer_orders

Not in this graph: customers is read by the view but has no declared depends_on edge to JOB_REPORT.

Data / SQL lineageWhich data produces which data
raw_orderssource table
reads
stg_ordersstaging table
reads
v_customer_ordersview: reads stg_orders + customers
writes
report_dailyconsumer report
customersloaded by another team
v_customer_orders
What this means for impact analysis

The scheduler knows JOB_REPORT waits for JOB_A. The data lineage also shows that report_daily depends on customers through v_customer_orders. The two graphs already describe different facts.

Why the two graphs disagree

  • A view hides its SQL inputs from the scheduler. The scheduler only sees the jobs and the dependencies someone declared. The view readsstg_orders and customers, but only the job relationship is declared.
  • A dependency can exist without data flow. A job may wait for an upstream job that writes nothing it reads — for example a cleanup, a gate or a notification job.
  • Data can flow without a dependency. Tables loaded by another team, external sources and manually maintained tables have lineage but no scheduler edge.
  • Dynamic SQL hides the edges. A query assembled at runtime can read different tables per execution, so neither static lineage nor declared dependencies fully describe it.
The two graphs answer different questions

“What runs next?” is an execution question. “Where did this value come from?” is a data question. A single graph cannot answer both without becoming ambiguous.

What this does to impact analysis

Impact analysis starts from a change — a late table, a corrected value, a failed job — and asks what else is affected. The answer depends on which graph you query:

Scheduler-only versus lineage-based impact analysis
ChangeScheduler graphData lineage graph
customers arrives lateNo impact path — no declared dependencyFinds report_daily as affected
JOB_A must be rerunShows which jobs to re-triggerShows which tables are rebuilt
JOB_REPORT is skippedShows the missed executionShows which data becomes stale

The practical rule: use lineage to enumerate affected data objects, then use the scheduler graph to plan the execution — which jobs to rerun and in what order. Neither is a substitute for the other.

Keeping the graphs aligned without over-declaring

  1. Derive candidate dependencies from lineage. If a job reads a table that another job writes, that is a candidate depends_on edge. Review it, do not declare it blindly.
  2. Mark external or shared tables explicitly. If customers is loaded outside the pipeline, record its owner and freshness expectation so the missing scheduler edge is a known decision.
  3. Do not declare every read. Adding a dependency for every table access can create cycles and unnecessary waits. Declare what must be ready before the job starts.
  4. Test the disagreement. Periodically compare the declared dependencies with the lineage of the queries. The differences are the places where impact analysis will be wrong.

Edge cases and trade-offs

  • View chains. Each view adds a layer the scheduler does not see. Lineage must expand through the view definition to find the real tables.
  • Temporary and staging tables. They create lineage edges that do not map to a durable scheduler dependency; decide whether they belong in the lineage graph.
  • Cross-team loads. A table loaded by another team may have an SLA but no job edge in this scheduler; a sensor or freshness check can make the wait explicit.
  • Column-level lineage. Table-level lineage answers “is this table affected”. Column-level lineage answers “is this field affected” and is more expensive to maintain.