Lineage Between Jobs and Tables
This feature requires an Enterprise or higher plan to use.
This feature is in Public Preview. See here for more information on what this means.
Lineage connects your ETL jobs to the warehouse tables they read and write. Once it exists, Monte Carlo can show which pipelines feed which tables, trace downstream impact when a job fails, and link pipeline health to data quality monitors on the affected tables.
There are two ways to produce it. They are independent — use either, or both together.
| Approach | How it works | Use when |
|---|---|---|
| Declared lineage | Your integration reports the input/output tables for each job, task, or run. | The source tool's API exposes which assets a job reads and writes. |
| SQL query tagging | You tag the SQL itself with the job's ID; Monte Carlo reads the tag from warehouse query logs. | A job runs free-form SQL the API can't introspect (scripts, stored procedures, dynamic queries). |
Declared lineage
Report the tables a job touches as inputs and outputs when you push pipeline data:
- Static lineage — set
inputs/outputson the EtlAsset (job) or its tasks. Use for tables a job always reads and writes. - Runtime lineage — set
inputs/outputson the EtlRunEvent. Use when the tables vary between runs.
Each entry is an asset reference — the asset type, its role, and its fully qualified name in the warehouse:
inputs=[AssetRef(asset_type="TABLE", role="INPUT", fully_qualified_name="raw.billing.charges")]
outputs=[AssetRef(asset_type="TABLE", role="OUTPUT", fully_qualified_name="staging.billing.charges_clean")]The fully_qualified_name must match how the table is identified in the monitored warehouse, so the edge attaches to the asset Monte Carlo already tracks.
See Push Ingest API and Custom Connectors for where these fields live in the schema.
SQL query tagging
When a job runs SQL that the source API can't introspect, tag the query with the job's identifier instead. Monte Carlo ingests the tag through its normal query-log collection on the monitored warehouse and resolves it back to your pipeline — no inputs/outputs and no extra integration code required.
Add a JSON comment to the SQL (or use a native query tag where the warehouse strips comments, e.g. Snowflake's QUERY_TAG):
-- {"mcd_job_id": "my-pipeline", "mcd_task_id": "my-task"}
INSERT INTO analytics.public.daily_revenue
SELECT ... FROM raw.billing.charges;The tag values are the same source_ids your integration already reports:
| Tag key | Value | Required |
|---|---|---|
mcd_job_id | The job's job_source_id. | Yes |
mcd_task_id | A task's task_source_id. | No — but requires mcd_job_id |
mcd_resource_id | The registered ETL connection's resource UUID. | Only to disambiguate (see below) |
Monte Carlo creates the table ↔ pipeline edges from the tables the query reads and writes: input tables become inputs of the job, output tables become outputs.
Requirements:
- The warehouse running the SQL is monitored by Monte Carlo with query logs enabled.
- The ETL integration is registered.
Multiple connections. If the same
mcd_job_idexists in more than one registered ETL connection, addmcd_resource_idwith the connection's resource UUID so Monte Carlo resolves the right one. Without it, an ambiguous tag is skipped.
Choosing an approach
- Prefer declared lineage when the source API exposes input/output tables — it's exact and doesn't depend on query logs.
- Use SQL query tagging for jobs whose lineage only lives in the SQL they run.
- Combine them: declare what the API knows, tag the queries it can't see. Both resolve to the same job and merge into one lineage graph.
Updated about 1 month ago
