Data Lineage Tools

Open Source and Column-Level Options (2026)

The main open source data lineage tools are OpenLineage with Marquez, the SQL parsers SQLLineage and SQLGlot, and the platforms DataHub and OpenMetadata. Databricks and Snowflake build column-level lineage into their platforms, and so does BigQuery. They capture lineage by different routes (job events or parsed SQL, or the platform's own query history), so the right one depends on where your transformations run and who reads the graph.

Last updated: Proudly published by: Jeff Wahl10 min read

What are data lineage tools?

Data lineage tools record where a dataset or column came from, which job produced it, and what consumes it next. That record answers 2 questions a data engineer gets every week: what breaks if I change this column, and where did this number come from. The open source options are OpenLineage with its Marquez server, the SQL parsers SQLLineage and SQLGlot, and the metadata platforms DataHub and OpenMetadata. Databricks Unity Catalog and Snowflake ship column-level lineage inside their own platforms, and so does BigQuery.

The names do not all mean the same kind of thing, which is why comparisons of them mislead. OpenLineage is a standard for collecting lineage metadata. Clients and integrations emit it. Marquez is a server that receives those events. DataHub and OpenMetadata are metadata platforms that store a graph and put search and ownership beside it, with a glossary on top, and both can take lineage from several routes. SQLLineage and SQLGlot are libraries that read SQL text. These layers combine more often than they compete: Google's lineage service imports OpenLineage events and OpenMetadata accepts them; DataHub's Airflow plugin builds on Airflow's OpenLineage support.

A lineage graph also serves a second job in data engineering work. It is the map you walk upstream during an incident, the one described in data observability, and the blast radius you read before a schema change. Data lineage as a concept, and the data catalog that usually hosts the graph, have their own guides.

Prepare for the interview
01 / Open invite
02min.

Know Data Lineage Tools the way the interviewer who asks it knows it.

a Data Lineage Tools query, the same shape a screen would give you.
The diff against expected. Where ties broke. What you missed.
sandbox
1source → bronze → silver → gold
2 ingest : CDC + Kafka
3 transform : dbt + Airflow
4 serve : Snowflake
5
Execute your solution0.4s avg.
TeslaInterview question
Solve a Data Lineage Tools problem

How lineage tools capture column lineage

Every tool gets its column edges by one of 3 routes, and the route decides what it can see. One route is events from the running job. The OpenLineage Spark integration walks the Spark logical plan and sends a columnLineage facet, and its documentation says this is on by default. It reads what Spark actually executed, so it sees through DataFrame code that no SQL parser could read. Its documented limit is JDBC sources, where a SQL parser reads only the query text and collects no field types or transformation types.

3 routes into 1 column lineage graph: a running job emits events, SQL text goes through a parser, and the platform's query history is read from its own log3 routes into 1 column lineage graph: a running job emits events, SQL text goes through a parser, and the platform's query history is read from its own log

Another route is parsing SQL text, which needs no access to the running system. SQLLineage prints column paths from a file with sqllineage -f test.sql -l column, and does not expand wildcards unless you give it metadata. SQLGlot's lineage function builds a column graph from a query plus a schema. dbt's column-level lineage relies on SQL parsing as well, and its documentation lists the failures: ambiguous or complex SQL, Python models that cannot be parsed, and hard-coded table names written instead of ref. OpenMetadata parses query logs. It tries SQLGlot first and falls back to SQLFluff and then SqlParse. It keeps only statements that move data: CTAS, INSERT ... SELECT, MERGE and view definitions.

A third route is the platform's own query history. Databricks captures lineage automatically for queries run on Databricks, and Snowflake records it between table-like objects. There's nothing to install, and nothing outside the platform is visible. If your pipeline touches both Spark and a warehouse, or adds a streaming system, expect to combine routes.

How OpenLineage describes a column edge

fields
Maps each output column to the input fields it depends on
inputFields
Each one names a column by namespace and dataset, and lists its transformations
dataset
Holds dataset-level indirect dependencies such as a sort column
DIRECT
The output value is derived from the input value
INDIRECT
The input affects the output without producing its value
IDENTITY, TRANSFORMATION, AGGREGATION
The 3 direct subtypes: taken as is, changed per row, combined across rows
JOIN, GROUP_BY, FILTER
Indirect subtypes for columns that decide which rows exist
SORT, WINDOW, CONDITIONAL
Indirect subtypes for ordering and window logic, and for branching

Direct vs indirect edges: a worked example

The OpenLineage column lineage facet separates a column that supplies a value from a column that only shapes the result. Take one query that returns 2 columns.

select
  o.order_id,
  sum(l.qty * l.unit_price) as revenue
from orders o
join order_lines l on l.order_id = o.order_id
where o.status = 'paid'
group by o.order_id

order_id is a DIRECT, IDENTITY copy of orders.order_id. revenue is a DIRECT AGGREGATION of order_lines.qty and order_lines.unit_price. That is 3 direct edges. The join reads orders.order_id and order_lines.order_id, the where reads orders.status, and the group by reads orders.order_id again. That is 4 indirect edges, 7 in all.

The column edges of 1 query: 3 direct edges link orders.order_id to order_id and order_lines.qty and unit_price to revenue; 4 indirect edges from join, filter and group by columns reach all outputsThe column edges of 1 query: 3 direct edges link orders.order_id to order_id and order_lines.qty and unit_price to revenue; 4 indirect edges from join, filter and group by columns reach all outputs

The indirect edges are the ones a select-list view drops. dbt's documentation says its column-level lineage reflects select statements and not other usage such as joins and filters, so a view of that kind draws 3 of 7 edges and hides 57% of the dependencies. The cost shows in impact analysis. Change the meaning of orders.status and a direct-only graph reports no affected output, while the filter edge reaches all 2, because a filter changes which rows exist for every column. When you compare tools, count edges against a query you have traced by hand.

Open source data lineage tools, one by one

OpenLineage is an Apache-2.0 project, at graduate stage in the LF AI & Data Foundation, with integrations that cover Spark and Flink as well as Airflow and dbt. Marquez, also Apache-2.0, is an open source metadata service that uses OpenLineage to collect metadata and draws dataset and job lineage. Its README does not mention column-level lineage, so check the version you deploy before you count on column edges from it. Choose this pair when the goal is a vendor-neutral event stream that more than one backend can read.

DataHub is Apache-2.0, with column-level lineage in its README feature list. Its Airflow plugin uses DataHub's SQL parser, which uses DataHub's metadata to generate column-level lineage, and the parser handles multi-statement SQL only when enable_multi_statement_sql_parsing is switched on. Manually declared inlets and outlets are table-level, so column lineage for a custom operator needs a custom extractor. Choose it when you want discovery and ownership in the same platform as lineage and your orchestration is Airflow.

OpenMetadata is Apache-2.0, with 130+ connectors and column-level lineage among its capabilities. It builds lineage from query logs and view definitions and accepts OpenLineage events. You can also edit table and column lineage by hand or through its REST API and Python SDK. Choose it when most of your lineage comes from warehouse query history and you want to patch the gaps manually.

SQLLineage is MIT-licensed and prints column paths from SQL files. SQLGlot is MIT-licensed, supports more than 30 dialects and its lineage function takes the SQL plus a schema. Choose these when lineage is a check in CI or a feature of your own tool and a server would be overhead. Spline is the Apache-2.0 option for Spark: its agent attaches as a query execution listener, and by default it tracks only persistent writes. Its documentation page does not state column-level detail, so verify that before choosing it for column lineage.

Open source lineage tools side by side

OpenLineage + Marquez
  • LicenseApache-2.0
  • What it isSpec and server
  • Column lineageFacet, per integration
  • Captured byJob events
  • Needs a serverMarquez server
DataHub
  • LicenseApache-2.0
  • What it isMetadata platform
  • Column lineageListed as a feature
  • Captured byIngestion, SQL parser
  • Needs a serverYes
OpenMetadata
  • LicenseApache-2.0
  • What it isMetadata platform
  • Column lineageListed as a feature
  • Captured byQuery logs, events
  • Needs a serverYes
SQLLineage
  • LicenseMIT
  • What it isPython library
  • Column lineageCLI, column mode
  • Captured byParsing SQL text
  • Needs a serverNo

Column-level lineage in dbt projects

dbt gives you lineage between models from ref and source calls with no extra tooling, and column-level lineage as a second layer. Its documentation describes 2 places to see it: Catalog in the dbt platform, which requires an Enterprise or Enterprise+ plan, and local development, which requires strict static analysis and is read with the column_lineage info option of dbt show. It labels a column Passthrough when it is reused unchanged and Rename when it's only renamed, and it shows the formula for a transformed one.

If you run dbt Core on a warehouse, the open source route is OpenLineage. openlineage-dbt supports 16 adapters, including BigQuery, Snowflake and Redshift, as well as Postgres, Databricks and DuckDB. It emits a columnLineage facet only when column-level parsing is enabled. A catalog such as DataHub or OpenMetadata can then show it next to the models. These configurations come up in dbt interview questions.

Column-level lineage built into Databricks, Snowflake and BigQuery

PlatformWhat it capturesHow long it keeps itDocumented limits
Databricks Unity CatalogColumn lineage automatically for queries run on Databricks, in SQL and the DataFrame APIIndefinitely in Catalog Explorer, a rolling 1 year in system tablesNo column lineage in the UI for path references, none for UDFs, and MERGE, UPDATE and DELETE are not reflected
SnowflakeColumn lineage between any 2 table-like objects, on Enterprise Edition or higher1 yearShared databases and INFORMATION_SCHEMA objects are excluded, and viewing needs the VIEW LINEAGE privilege
BigQuery, through Google Cloud lineageColumn lineage for BigQuery jobs once the Data Lineage API is enabled30 daysNo column lineage for load jobs or routines, jobs with over 1,500 column links fall back to table level, and only top-level columns are covered

Where column-level lineage goes missing

Every route has a blind spot, and the blind spots decide which tool fits. Parsers fail on SQL they cannot read, and the failure can be quiet: wildcards stay unexpanded without metadata, and a table named by a string instead of a reference never links. Event-based capture sees only jobs that were instrumented, so a script run by hand leaves no edge. Platform logs see only that platform, and each documents statement types it skips.

Silent downgrades are another gap. A tool that cannot resolve a column mapping can fall back to table level without saying so, as Google's lineage does for a BigQuery job over 1,500 column links. A graph that looks complete at table level can then have no column edges for exactly the wide, heavily transformed tables where you need them. Ask each tool how it reports a statement it couldn't parse.

Another gap is what the graph means. A tool that draws only select-list edges answers where a value came from but not what else a column affects, and one that mixes the 2 without labels makes impact analysis noisy. Prefer tools that keep the DIRECT and INDIRECT distinction visible.

Which data lineage tool fits which situation

If your transformations run almost entirely inside 1 warehouse, its built-in lineage is the smallest step: nothing to deploy, though you accept that platform's retention and statement limits. If the work spans Spark jobs and an Airflow and dbt setup, an event standard such as OpenLineage keeps instrumentation neutral, and a backend can change later without re-instrumenting.

If the people asking lineage questions are analysts and owners rather than the platform team, put the graph next to search and ownership with DataHub or OpenMetadata, at the cost of running a platform. If lineage is a CI check, such as failing a pull request that drops a column something reads, a parser library is enough and a server is overhead. If your SQL is in dbt and the Enterprise plan is available, its Catalog shows column lineage with no extra system, while a project on Core can emit events through openlineage-dbt.

None of these choices is permanent, and most mature setups run 2 of them. Practicing the reasoning matters more than the tool name in a loop: data pipeline interview questions and data pipeline practice problems cover how to trace and defend a pipeline, and the system design round is where an interviewer asks how you would find what a change breaks.

How to test a lineage tool on your own queries

Pick 4 queries from your own warehouse: a join with a filter and a group by, a MERGE, a query with a wildcard, and one that calls a user-defined function. Write the expected direct and indirect edges for each by hand, so you hold a number to compare against.

Run each tool on the same 4 and count the edges it finds against your list. Note what it misses: edges of either kind, or whole statements. Finally feed it 1 query it can't parse and see whether it flags the gap, drops to table level or shows nothing. A tool that fails loudly is easier to trust than one that fails with a clean-looking graph.

Data lineage tools FAQ

What are the best open source data lineage tools?+
It depends on what you already run. OpenLineage is a standard with integrations for Spark and Airflow, and also for dbt and Flink. Marquez is an open source server that stores its events. DataHub and OpenMetadata are full metadata platforms that show lineage next to ownership and search. SQLLineage and SQLGlot parse SQL text with no server at all. Pick by where your transformations run and who needs to see the graph.
Which tools support column-level lineage?+
DataHub and OpenMetadata list it as a feature. OpenLineage defines a column lineage facet that integrations such as Spark fill in. SQLLineage and SQLGlot compute it from SQL text. dbt documents it for the dbt platform on Enterprise plans and for local development with strict static analysis. Databricks Unity Catalog and Snowflake capture it inside their own platforms, and BigQuery lineage in Google Cloud collects it for BigQuery jobs.
Is OpenLineage a tool or a standard?+
A standard. It defines a model where a run of a job reads and writes datasets, with facets that extend it, for collecting lineage while jobs execute. It is hosted by the LF AI & Data Foundation. You still need a backend to store and draw what it emits. Marquez or a cloud catalog works, as does a platform such as DataHub or OpenMetadata.
What is the difference between table-level and column-level lineage?+
Table-level lineage says that one table is built from other tables. Column-level lineage says which input columns produce each output column, and how: copied unchanged, or computed per row or by aggregation. A complete view also records indirect dependencies, such as a column used only in a filter, or in a join or group by.
How long do the platforms keep lineage?+
Google Cloud keeps lineage for 30 days. Snowflake retains table and column lineage for 1 year. Databricks keeps it indefinitely in Catalog Explorer for lineage captured after September 1, 2024. Its system tables expose a rolling 1 year window. Self-hosted tools keep what their own store keeps, so retention is a setting you control.
Why is my column lineage incomplete?+
The usual causes are SQL a parser cannot read, such as Python models, hard-coded table names or complex lateral joins, queries that run outside the platform that records lineage, user-defined functions that hide the column mapping, and statements the tool skips, such as MERGE on Databricks along with UPDATE and DELETE. Test the tool on your own queries before you rely on its graph.
02 / Why practice

The candidate who gets the offer

  1. 01

    Reading a solution is not the same as writing one

    Every engineer who has frozen on a query they had read a dozen times knows the gap. The only preparation that closes it is producing the answer yourself, under time, before the interview does it for you

  2. 02

    76% of hiring managers reject on the coding task, not the resume

    From HackerRank's 2024 Developer Skills Report. Candidates who look strong on paper still fail the live screen if they haven't done timed, executable practice

  3. 03

    System design comes down to the calls you defend out loud

    Ingestion, batch vs streaming, the bronze/silver/gold layers, idempotency, backfill and replay. Sketching the pipeline and naming the failure modes is the signal, not the boxes

Related guides