Skip to main content

What is Data Lineage?

Data Lineage is a map of how data flows through your systems: where it originates, what transforms it, and what depends on it downstream. In the context of Portal, lineage can provide visibility into the relationships between the workflow and dataset entities in your catalog.

Why Data Lineage?

At a high level, lineage can answer questions like:
  • “What required ancillary data must flow for this dataset to be fresh today?”
  • “If I deprecate this dataset, what will it break downstream?”
  • “Which workflow produces this dataset and where did it read from?”
  • “If my dataset is ‘late’, where exactly is the blockage upstream?”

Prerequisites

Before you begin, ensure you have the following:
  • A Portal instance URL — e.g. https://<YOUR INSTANCE>.spotifyportal.com
  • An External Access token — Follow the Create an API key guide to generate a static token under Admin → App Settings → External access. There is no need to provide access to any specific plugin or RBAC permission.
  • Datasets ingested into the catalog (optional but recommended) — If you want lineage events to link to catalog entities, ensure your datasets have been ingested via one of the Data Experience warehouse integrations. Lineage events will still be accepted without this, but dataset nodes will appear as “unlinked” in the graph.

Quick Setup

  1. Using the External Access token from Prerequisites, set the following environment variables:
  2. Try a simple curl command:
  3. If the curl response status code is 201, validate the event was received by visiting: https://<YOUR INSTANCE>.spotifyportal.com/data-overview/lineage

How does it work?

Portal implements the OpenLineage specification to collect and analyze lineage. Lineage run events can be consumed from any orchestrator that is capable of emitting HTTP requests, including Apache Airflow, Apache Spark, Apache Flink, dbt, Dagster, Feast, and many more. This entails using bipartite Graph conventions and standardized node ID formats for representing dataset-workflow relationships through directed acyclic graphs (DAGs). In practice, this means when your orchestrator runs a job, it sends an event to Portal describing which datasets it read from and wrote to. Portal uses these events to build a graph you can explore on any dataset or workflow entity page.

OpenLineage Run Events

Portal’s OpenLineage endpoint accepts one type of event: the RunEvent.
OpenLineage run event
lifecycle
A RunEvent reports the status of a specific run for a job, with specific input and/or output data, at a specific point in time. The most important fields are explained here below.

Event type

Event type informs the state of the execution. Each batch job should ideally emit a RunEvent with START state when it starts, followed by one of the terminal events when it finishes the processing for any reason:
OpenLineage event
types
For long-running processes like stream processing pipelines, you can additionally send updates using RUNNING state to report things like “changes in the run or emit performance metrics”.
OpenLineage RUNNING event
type

Event Time

Since the only event that is emitted is called a RunEvent, it is important to report when each phase of the execution takes place. Timestamps must be in RFC 3339 / ISO 8601 format with an explicit UTC offset (Z or +HH:MM), e.g. 2026-08-12T13:16:00Z

Namespace

Consult the OpenLineage Naming Conventions for which value to use according to your data source.

Mapping lineage to catalog entities

The lineage graph is bipartite: edges always connect a workflow to a dataset, never workflow-to-workflow or dataset-to-dataset. In your RunEvent, job becomes a Workflow node, while each entry in inputs and outputs becomes a Dataset node. Portal automatically links lineage nodes to catalog entities when the namespace and name in your RunEvent match a dataset that has already been ingested via a Data Experience warehouse integration. Linked datasets show full lineage on their entity page under the Lineage tab. If a referenced dataset has not yet been ingested into the catalog, the node still appears in the graph but is shown as “unlinked” with dimmed styling. Ingesting the dataset later will automatically establish that link.

Dataset and job naming conventions

For lineage events to link to your cataloged datasets, the namespace and name values in your RunEvent must match what Portal has on file. The key fields are: The most common reason for missing lineage is a namespace or name mismatch — for example, publishing bigquery with name myproject.raw.orders when the catalog has myproject.raw.orders_v2. Check the Dataset entity page in Portal to confirm the expected values. Consult the OpenLineage Naming Conventions for general rules on deriving namespace and name values for each data source type.

Integration with your orchestrator

For production setups, you will typically use your orchestrator’s OpenLineage client rather than manual curl commands. Any orchestrator capable of emitting HTTP requests can push OpenLineage Run Events to Portal’s POST /api/data-registry/lineage endpoint. The environment variables from Quick Setup (OPENLINEAGE_URL, OPENLINEAGE_ENDPOINT, OPENLINEAGE_API_KEY) apply to most integrations. Requests must provide the credential within the Authorization: Bearer <token> header. If you own a system that can utilize one of the out-of-the-box OpenLineage integrations for reporting lineage, consider using them before trying to directly interact with the API. See the subsections below for framework-specific guidance.

dbt

dbt has first-class OpenLineage support. See the OpenLineage dbt integration docs for setup instructions. Point the integration at Portal by setting OPENLINEAGE_URL, OPENLINEAGE_ENDPOINT, and OPENLINEAGE_API_KEY as described in Quick Setup.

Apache Airflow

Airflow 2.7+ includes a native OpenLineage provider. See the Airflow OpenLineage provider docs for setup instructions. Point the integration at Portal by setting OPENLINEAGE_URL, OPENLINEAGE_ENDPOINT, and OPENLINEAGE_API_KEY as described in Quick Setup.

Viewing Data Lineage in Portal

You can visualise the Lineage of any dataset on Portal, under the Lineage tab on the Catalog dataset entity page. By default it displays upstream only and a depth of 1.
Lineage graph on dataset entity
page
Additionally, the last pipeline run information is displayed on a card on the entity overview tab.
Last pipeline run card on dataset entity
overview
You can also view the overall run event history in a table on the Lineage tab on the Data Experience page.
Lineage run event history table on Data Experience
page

Troubleshooting

This section covers common issues when sending lineage events or viewing the graph. When debugging, check these areas first:
  1. The HTTP response code from POST /api/data-registry/lineage — a non-201 response indicates the event was rejected.
  2. Your token configuration — ensure the External Access token is valid and included in the Authorization: Bearer <token> header.
  3. Namespace and name matching — verify that the namespace and name values in your RunEvent match exactly what is registered in the catalog.

Authentication errors (401/403)

Requests must include an Authorization: Bearer <token> header with a valid External Access token. See the Create an API key guide for how to generate one under Admin → App Settings → External access. If you receive a 401 or 403 response, check the following:
  • Missing or invalid Bearer token: Ensure the Authorization: Bearer <token> header is present and the token value is correct.
  • Token not configured: Verify that the token has been saved under Admin → App Settings → External access.
  • Expired or rotated token: If the token was recently rotated, ensure you are using the new value.
See the Create an API key guide for instructions on generating a new token.

Malformed or rejected events

If the POST /api/data-registry/lineage endpoint returns a non-201 response, the event was rejected. A 400 Bad Request response includes a detailed error message, e.g. Invalid OpenLineage RunEvent: .... Common causes:
  • Invalid JSON: The request body is not valid JSON.
  • Missing required fields: The following fields are required: eventType, eventTime, run (with runId), job (with namespace and name), producer, and schemaURL.
  • Invalid eventType: Must be one of START, RUNNING, COMPLETE, ABORT, FAIL, or OTHER.
  • Invalid eventTime: Must be an ISO-8601 timestamp including timezone offset, e.g. "2026-08-03T19:40:00.000Z".
  • Wrong schemaURL: Should be https://openlineage.io/spec/2-0-2/OpenLineage.json.
A successful 201 Created response returns:

Lineage not appearing in the graph

If your events are accepted (201 response) but the lineage graph is empty or incomplete, the most common causes are:
  • Namespace/name mismatch: The most common reason for missing lineage is a mismatch between the namespace or name in your RunEvent and what is registered in the catalog. Your workflow might publish bq://project/dataset/table but your catalog dataset is registered with a different URI. Verify the values match exactly against the Dataset entity page in Portal.
  • Datasets not registered in the catalog: Unregistered datasets still appear in the graph but as dimmed, unlinked nodes with no entity page link. Ingest them via a Data Experience warehouse integration to get full lineage on the entity page.
  • Upstream datasets not registered: Unregistered upstreams also render as unlinked nodes. Check with the owners of your upstream data to verify that their data has been ingested.
  • Only START event sent: If you only send a START event without a terminal event (COMPLETE, FAIL, or ABORT), the lineage graph may not update fully. Ensure each run emits both a START and a terminal event.
  • Wrong Portal instance: Verify that OPENLINEAGE_URL points to the correct Portal instance where your datasets are cataloged.
  • Unlinked nodes: When Portal cannot reconcile a dataset node against the Data Registry, the node is still created but with dataset_id: null. These unlinked nodes are kept in the graph to avoid creating holes when traversing, but appear with dimmed styling in the UI. A notification is sent to the Portal instance admin when unlinked events are received.

Next Steps