<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed Moussa</title>
    <description>The latest articles on DEV Community by Ahmed Moussa (@amoussa-eduhub).</description>
    <link>https://dev.to/amoussa-eduhub</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3929502%2Fdebcd69b-3259-40f6-ac48-8b21525743f2.png</url>
      <title>DEV Community: Ahmed Moussa</title>
      <link>https://dev.to/amoussa-eduhub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amoussa-eduhub"/>
    <language>en</language>
    <item>
      <title>How to Automate SOC2 and GDPR Compliance Scans with ComplianceWeave</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 15 Aug 2026 05:45:02 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/how-to-automate-soc2-and-gdpr-compliance-scans-with-complianceweave-15g6</link>
      <guid>https://dev.to/amoussa-eduhub/how-to-automate-soc2-and-gdpr-compliance-scans-with-complianceweave-15g6</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automated&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;My&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;SOC2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Audit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Prep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;an&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Afternoon&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(And&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Too)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Picture this: it's 11 PM, three weeks before your SOC2 audit, and you're manually screenshotting AWS console pages into a Google Doc labeled &lt;span class="sb"&gt;`evidence_FINAL_v3_USE_THIS_ONE.docx`&lt;/span&gt;.

We've all been there. Or we've &lt;span class="ge"&gt;*heard*&lt;/span&gt; the war stories.

This tutorial is the exit ramp from that highway to misery. We're going to wire up &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; to your infrastructure and have it do the evidence-hunting while you do literally anything else.

By the end, you'll have a Python script that scans your environment, surfaces gaps, triggers remediation, and hands you a polished audit report — automatically.

Let's build it.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## What We're Working With&lt;/span&gt;

ComplianceWeave exposes three endpoints that, chained together, form a complete compliance automation loop:

| Endpoint | What it does |
|---|---|
| &lt;span class="sb"&gt;`POST /compliance/scan`&lt;/span&gt; | Kicks off an infrastructure scan against your chosen frameworks |
| &lt;span class="sb"&gt;`GET /compliance/reports`&lt;/span&gt; | Fetches generated audit-ready reports |
| &lt;span class="sb"&gt;`POST /compliance/remediate`&lt;/span&gt; | Auto-remediates fixable violations |

We'll use all three. In order. Like sensible engineers.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Prerequisites&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install requests python-dotenv rich&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
We're using `rich` for readable terminal output because staring at raw JSON at 11 PM is a form of self-harm.

Create a `.env` file:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
COMPLIANCEWEAVE_API_KEY=your_api_key_here&lt;br&gt;
COMPLIANCEWEAVE_BASE_URL=&lt;a href="https://api.complianceweave.io/v1" rel="noopener noreferrer"&gt;https://api.complianceweave.io/v1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Step 1: Set Up Your Client

First, let's build a small, reusable client so we're not copy-pasting headers into every request.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  compliance_client.py
&lt;/h1&gt;

&lt;p&gt;import os&lt;br&gt;
import time&lt;br&gt;
import requests&lt;br&gt;
from dotenv import load_dotenv&lt;br&gt;
from rich.console import Console&lt;br&gt;
from rich.panel import Panel&lt;/p&gt;

&lt;p&gt;load_dotenv()&lt;br&gt;
console = Console()&lt;/p&gt;

&lt;p&gt;class ComplianceWeaveClient:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self):&lt;br&gt;
        self.api_key = os.getenv("COMPLIANCEWEAVE_API_KEY")&lt;br&gt;
        self.base_url = os.getenv("COMPLIANCEWEAVE_BASE_URL")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if not self.api_key:
        raise EnvironmentError(
            "COMPLIANCEWEAVE_API_KEY not set. "
            "Check your .env file."
        )

    self.session = requests.Session()
    self.session.headers.update({
        "Authorization": f"Bearer {self.api_key}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    })

def _request(self, method, endpoint, **kwargs):
    url = f"{self.base_url}{endpoint}"
    try:
        response = self.session.request(method, url, **kwargs)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        console.print(f"[bold red]HTTP Error:[/bold red] {e.response.status_code} — {e.response.text}")
        raise
    except requests.exceptions.ConnectionError:
        console.print("[bold red]Connection failed.[/bold red] Is the API URL correct?")
        raise
    except requests.exceptions.Timeout:
        console.print("[bold red]Request timed out.[/bold red] Try again or check your network.")
        raise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Why a session object?** It reuses the TCP connection across requests, which matters when you're hitting the API repeatedly during a scan-poll loop. Small wins add up.

---

## Step 2: Trigger a Compliance Scan

Now let's initiate a scan. ComplianceWeave lets you specify which frameworks to check — we'll target SOC2 and GDPR simultaneously.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  scan.py
&lt;/h1&gt;

&lt;p&gt;from compliance_client import ComplianceWeaveClient, console&lt;br&gt;
from rich.progress import Progress, SpinnerColumn, TextColumn&lt;br&gt;
import time&lt;/p&gt;

&lt;p&gt;def run_scan(client, frameworks=None, environment="production"):&lt;br&gt;
    if frameworks is None:&lt;br&gt;
        frameworks = ["SOC2", "GDPR"]&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.print(Panel(
    f"Starting scan for: [bold cyan]{', '.join(frameworks)}[/bold cyan]\n"
    f"Environment: [bold]{environment}[/bold]",
    title="🔍 ComplianceWeave Scan"
))

payload = {
    "frameworks": frameworks,
    "environment": environment,
    "options": {
        "deep_scan": True,         # Check resource-level configs, not just account-level
        "include_remediation": True # Flag auto-fixable issues
    }
}

response = client._request("POST", "/compliance/scan", json=payload)
scan_id = response.get("scan_id")

if not scan_id:
    raise ValueError("No scan_id returned. Something went wrong on the API side.")

console.print(f"[green]✓ Scan initiated.[/green] ID: [bold]{scan_id}[/bold]")

# Poll until the scan completes
with Progress(
    SpinnerColumn(),
    TextColumn("[progress.description]{task.description}"),
    transient=True,
) as progress:
    task = progress.add_task("Scanning infrastructure...", total=None)

    while True:
        status_response = client._request("GET", f"/compliance/scan/{scan_id}")
        status = status_response.get("status")

        if status == "completed":
            progress.stop()
            break
        elif status == "failed":
            raise RuntimeError(f"Scan failed: {status_response.get('error', 'Unknown error')}")

        time.sleep(10)  # Don't hammer the API

console.print(f"[green]✓ Scan complete.[/green]")
return status_response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
╭──────────────── 🔍 ComplianceWeave Scan ────────────────╮&lt;br&gt;
│ Starting scan for: SOC2, GDPR                           │&lt;br&gt;
│ Environment: production                                 │&lt;br&gt;
╰─────────────────────────────────────────────────────────╯&lt;br&gt;
✓ Scan initiated. ID: scan_a3f92b1c&lt;br&gt;
⠸ Scanning infrastructure...&lt;br&gt;
✓ Scan complete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The polling loop is intentional. Scans against real infrastructure take time — fighting that with impatient code just gets you incomplete results.

---

## Step 3: Auto-Remediate What You Can

Before pulling the report, let's fix the low-hanging fruit. ComplianceWeave flags issues it can remediate automatically (think: misconfigured S3 bucket ACLs, overly permissive security groups, missing encryption settings).

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  remediate.py
&lt;/h1&gt;

&lt;p&gt;from compliance_client import ComplianceWeaveClient, console&lt;br&gt;
from rich.table import Table&lt;/p&gt;

&lt;p&gt;def remediate_violations(client, scan_results):&lt;br&gt;
    violations = scan_results.get("violations", [])&lt;br&gt;
    auto_fixable = [v for v in violations if v.get("auto_remediable") is True]&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if not auto_fixable:
    console.print("[yellow]No auto-remediable violations found.[/yellow] Manual review required for all issues.")
    return []

table = Table(title="Auto-Remediating Violations")
table.add_column("Resource", style="cyan")
table.add_column("Issue", style="yellow")
table.add_column("Framework", style="magenta")

for v in auto_fixable:
    table.add_row(v["resource_id"], v["description"], v["framework"])

console.print(table)

violation_ids = [v["violation_id"] for v in auto_fixable]

payload = {
    "violation_ids": violation_ids,
    "dry_run": False  # Set True to preview changes without applying
}

result = client._request("POST", "/compliance/remediate", json=payload)

fixed = result.get("remediated", [])
failed = result.get("failed", [])

console.print(f"[green]✓ Fixed {len(fixed)} violation(s).[/green]")
if failed:
    console.print(f"[red]✗ {len(failed)} remediation(s) failed.[/red] Check the report for details.")

return fixed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; **Best practice:** Always run with `dry_run: True` first in a staging environment. Automated remediation is powerful. So is accidentally locking yourself out of a resource.

---

## Step 4: Pull Your Audit-Ready Report

The scan is done, violations are patched. Time to collect your evidence.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  report.py
&lt;/h1&gt;

&lt;p&gt;from compliance_client import ComplianceWeaveClient, console&lt;br&gt;
import json&lt;br&gt;
from datetime import datetime&lt;/p&gt;

&lt;p&gt;def fetch_report(client, scan_id, output_format="pdf"):&lt;br&gt;
    console.print(f"\n[bold]Fetching report for scan:[/bold] {scan_id}")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;params = {
    "scan_id": scan_id,
    "format": output_format,   # "pdf", "json", or "csv"
    "include_evidence": True,  # Attach raw evidence artifacts
    "frameworks": ["SOC2", "GDPR"]
}

report = client._request("GET", "/compliance/reports", params=params)

# Save the report locally
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"compliance_report_{timestamp}.json"

with open(filename, "w") as f:
    json.dump(report, f, indent=2)

# Print a human-readable summary
summary = report.get("summary", {})
console.print(f"\n[bold green]Report Summary[/bold green]")
console.print(f"  Overall Score:     {summary.get('compliance_score', 'N/A')}%")
console.print(f"  Controls Passed:   {summary.get('controls_passed', 0)}")
console.print(f"  Controls Failed:   {summary.get('controls_failed', 0)}")
console.print(f"  Report saved to:   [cyan]{filename}[/cyan]")

return report, filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Fetching report for scan: scan_a3f92b1c&lt;/p&gt;

&lt;p&gt;Report Summary&lt;br&gt;
  Overall Score:     91%&lt;br&gt;
  Controls Passed:   147&lt;br&gt;
  Controls Failed:   13&lt;br&gt;
  Report saved to:   compliance_report_20240315_143022.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Step 5: Wire It All Together

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  main.py
&lt;/h1&gt;

&lt;p&gt;from compliance_client import ComplianceWeaveClient, console&lt;br&gt;
from scan import run_scan&lt;br&gt;
from remediate import remediate_violations&lt;br&gt;
from report import fetch_report&lt;/p&gt;

&lt;p&gt;def main():&lt;br&gt;
    client = ComplianceWeaveClient()&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1. Scan
scan_results = run_scan(
    client,
    frameworks=["SOC2", "GDPR", "HIPAA"],
    environment="production"
)

# 2. Remediate what we can
remediate_violations(client, scan_results)

# 3. Re-scan to capture remediation (optional but recommended for auditors)
final_results = run_scan(client, frameworks=["SOC2", "GDPR", "HIPAA"])

# 4. Generate the report
report, filename = fetch_report(
    client,
    scan_id=final_results["scan_id"]
)

console.print(f"\n[bold green]✓ Done.[/bold green] Hand [cyan]{filename}[/cyan] to your auditor.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    main()&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## What You Actually Built

In ~150 lines of Python, you now have:

- **Automated evidence collection** across SOC2, GDPR, HIPAA, and ISO 27001
- **Intelligent remediation** that fixes what it safely can
- **Audit-ready reports** generated without a single screenshot

The real win isn't the code — it's the meeting you won't have to schedule to explain why the evidence doc is named `FINAL_v3_USE_THIS_ONE`.

Schedule this as a weekly cron job. Let ComplianceWeave run continuously. Show up to your audit with a folder of timestamped reports instead of a folder of regrets.

Your future self, three weeks before the next audit, will thank you.

---

*Questions? Drop them in the comments. I check. Eventually.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introducing ComplianceWeave -- Automated Compliance Monitoring for DevSecOps Teams</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 15 Aug 2026 05:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/introducing-complianceweave-automated-compliance-monitoring-for-devsecops-teams-2hoa</link>
      <guid>https://dev.to/amoussa-eduhub/introducing-complianceweave-automated-compliance-monitoring-for-devsecops-teams-2hoa</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automated&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Part&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;My&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Job&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;That&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Making&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Me&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Quit"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;devsecops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

There's a specific kind of dread that hits on a Tuesday afternoon when your Slack lights up with: &lt;span class="ge"&gt;*"Audit prep starts next week. Can you pull together the evidence package?"*&lt;/span&gt;

You know what that means. Three weeks of:
&lt;span class="p"&gt;-&lt;/span&gt; Digging through CloudTrail logs like an archaeologist
&lt;span class="p"&gt;-&lt;/span&gt; Exporting CSVs from five different dashboards
&lt;span class="p"&gt;-&lt;/span&gt; Writing the same "here's what we do for access control" paragraph for the fourth time this year
&lt;span class="p"&gt;-&lt;/span&gt; Discovering, on day twelve, that one Lambda function has been logging to an unencrypted bucket since March

I've been that engineer. I've also been the one who &lt;span class="ge"&gt;*caused*&lt;/span&gt; that Lambda situation. Neither role is fun.

This is why we built &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; — continuous infrastructure compliance monitoring that generates audit-ready reports automatically, across SOC2, GDPR, HIPAA, and ISO 27001, without the quarterly fire drill.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Actual Problem (Not the Sales Version)&lt;/span&gt;

Point-in-time audits are a lie we tell ourselves.

You scramble, you clean up, you document, you pass. Then six weeks later someone deploys a new service and forgets to tag it, or a contractor account doesn't get deprovisioned, or MFA enforcement drifts because someone was fighting a production incident and temporarily loosened a policy.

Compliance isn't a state you achieve. It's a state you &lt;span class="ge"&gt;*maintain*&lt;/span&gt;. And maintaining it manually, across multiple frameworks that all care about slightly different things, is a full-time job that nobody actually has time for.

ComplianceWeave treats compliance like you treat uptime: something you monitor continuously, alert on when it breaks, and have runbooks for.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Quick Start&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install complianceweave&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Set your API key and point it at your infrastructure:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import complianceweave as cw&lt;/p&gt;

&lt;p&gt;client = cw.Client(api_key="cw_live_...")&lt;br&gt;
scan = client.scan(frameworks=["soc2", "gdpr"], target="aws://us-east-1")&lt;br&gt;
print(scan.summary())&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
That's it. Within minutes you'll have a gap analysis across both frameworks, ranked by severity, with control IDs mapped to the actual resources causing the finding.

No YAML manifests. No agent to deploy. No "contact sales to enable this feature."

---

## Real-World Use Case: Catching Drift Before Your Auditor Does

Here's a pattern I see constantly: a team passes their SOC2 Type II audit in Q1, then spends the rest of the year building features. By Q4, when the next audit window opens, they've accumulated months of compliance drift they don't know about.

Let's say you want to run ComplianceWeave as part of your CI/CD pipeline — not just scanning prod, but catching violations before they ever merge.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import complianceweave as cw&lt;br&gt;
import sys&lt;/p&gt;

&lt;p&gt;client = cw.Client(api_key="cw_live_...")&lt;/p&gt;
&lt;h1&gt;
  
  
  Scan a staging environment after infrastructure changes
&lt;/h1&gt;

&lt;p&gt;scan = client.scan(&lt;br&gt;
    frameworks=["soc2", "hipaa"],&lt;br&gt;
    target="aws://us-west-2",&lt;br&gt;
    environment="staging",&lt;br&gt;
    severity_threshold="medium"&lt;br&gt;
)&lt;/p&gt;
&lt;h1&gt;
  
  
  Get auto-generated remediation plans for any findings
&lt;/h1&gt;

&lt;p&gt;if scan.has_violations():&lt;br&gt;
    for violation in scan.violations:&lt;br&gt;
        print(f"[{violation.severity.upper()}] {violation.control_id}: {violation.title}")&lt;br&gt;
        print(f"  Resource: {violation.resource_arn}")&lt;br&gt;
        print(f"  Fix: {violation.remediation.description}")&lt;br&gt;
        print(f"  Terraform: {violation.remediation.iac_snippet}\n")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Fail the pipeline if critical violations exist
if scan.critical_count &amp;gt; 0:
    print(f"❌ {scan.critical_count} critical violation(s) found. Blocking deploy.")
    sys.exit(1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;print(f"✅ Scan complete. {scan.passing_controls}/{scan.total_controls} controls passing.")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Sample output:**

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
[HIGH] CC6.1: Encryption at rest not enabled&lt;br&gt;
  Resource: arn:aws:rds:us-west-2:123456789:db/user-data-staging&lt;br&gt;
  Fix: Enable storage encryption on RDS instance. Note: requires snapshot restore for existing instances.&lt;br&gt;
  Terraform: storage_encrypted = true&lt;/p&gt;

&lt;p&gt;[MEDIUM] GDPR-Art32: Data processing logs retained beyond policy window&lt;br&gt;
  Resource: arn:aws:logs:us-west-2:123456789:log-group:/app/user-events&lt;br&gt;
  Fix: Set retention policy to 90 days per your DPA.&lt;br&gt;
  Terraform: retention_in_days = 90&lt;/p&gt;

&lt;p&gt;✅ Scan complete. 47/49 controls passing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The remediation plans aren't generic advice — they're generated from the actual resource configuration, with IaC snippets you can drop directly into your Terraform. When your auditor asks "how do you ensure encryption at rest?", your answer isn't a doc you wrote last February. It's a dashboard showing continuous enforcement and a git history of remediations.

---

## Multi-Framework, Without the Redundancy

One thing that's genuinely annoying about compliance is that SOC2, HIPAA, and ISO 27001 all care about encryption, access control, and audit logging — they just call them different things and ask for slightly different evidence.

ComplianceWeave maps controls across frameworks automatically. If your S3 bucket encryption satisfies SOC2 CC6.1, we tell you it also satisfies HIPAA §164.312(a)(2)(iv) and ISO 27001 A.10.1.1. You fix it once, it counts everywhere.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  See which frameworks a single remediation satisfies
&lt;/h1&gt;

&lt;p&gt;violation = scan.violations[0]&lt;br&gt;
print(violation.cross_framework_mappings)&lt;/p&gt;
&lt;h1&gt;
  
  
  {
&lt;/h1&gt;
&lt;h1&gt;
  
  
  "soc2": "CC6.1",
&lt;/h1&gt;
&lt;h1&gt;
  
  
  "hipaa": "§164.312(a)(2)(iv)",
&lt;/h1&gt;
&lt;h1&gt;
  
  
  "iso27001": "A.10.1.1"
&lt;/h1&gt;
&lt;h1&gt;
  
  
  }
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
For startups navigating their first SOC2 while also trying to land an enterprise customer who wants HIPAA attestation, this is the difference between two parallel workstreams and one.

---

## Generating Audit Reports

When the auditor actually shows up:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
report = client.generate_report(&lt;br&gt;
    framework="soc2",&lt;br&gt;
    period_start="2024-01-01",&lt;br&gt;
    period_end="2024-12-31",&lt;br&gt;
    format="pdf"  # or "json", "csv"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;report.save("soc2_type2_evidence_2024.pdf")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The report includes control status over time (not just current state), evidence timestamps, resource inventory, and a change log of every violation and remediation. It's the audit package, assembled automatically from twelve months of continuous monitoring.

---

## What We're Not

We're not a SIEM. We're not trying to replace your security team's threat detection. We're not a checkbox tool that gives you a passing score while your infrastructure is actually on fire.

ComplianceWeave is infrastructure compliance infrastructure. It's the layer that answers "are we compliant?" continuously, so that question stops being a project and starts being a metric.

---

## Try It

The API is live. The Python client is open source.

- **⭐ Star the client library**: [github.com/complianceweave/complianceweave-python](https://github.com/complianceweave/complianceweave-python)
- **🚀 Start a free scan**: [complianceweave.io/start](https://complianceweave.io/start) — no credit card, scans your first framework free
- **📖 Read the docs**: [docs.complianceweave.io](https://docs.complianceweave.io)

If you've got questions about integrating into your pipeline, or want to talk through a specific framework requirement, drop a comment below. I read all of them.

---

*Built by engineers who have been on both sides of the audit table. We know what auditors actually look for, and we know what "three weeks of evidence collection" does to a team's morale.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ComplianceWeave vs Vanta, Drata, Secureframe: Which Compliance Automation Tool Should You Use?</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 08 Aug 2026 06:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-5h8h</link>
      <guid>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-5h8h</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compliance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2024:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ComplianceWeave&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vs.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Field&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(An&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Engineer's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Honest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Take)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Compliance Automation in 2024: ComplianceWeave vs. The Field (An Engineer's Honest Take)&lt;/span&gt;

There's a particular kind of dread that descends on engineering teams roughly six weeks before an audit. You know the feeling — suddenly everyone is a compliance expert, Slack fills with panicked messages about evidence screenshots, and someone is manually exporting CSV files from five different dashboards at 11pm.

Compliance automation tools exist to prevent exactly this. But the market has gotten crowded, and the differences between products are genuinely meaningful depending on &lt;span class="ge"&gt;*who you are*&lt;/span&gt; as a team. Let's cut through the noise.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Landscape at a Glance&lt;/span&gt;

Before diving deep, here's where the major players land across the dimensions that actually matter to engineering teams:

| Feature | ComplianceWeave | Vanta | Drata | Tugboat Logic |
|---|---|---|---|---|
| &lt;span class="gs"&gt;**Pricing model**&lt;/span&gt; | Usage-based + self-hosted tier | Per-employee SaaS | Per-employee SaaS | Per-framework SaaS |
| &lt;span class="gs"&gt;**Self-hosted option**&lt;/span&gt; | ✅ Yes | ❌ No | ❌ No | ❌ No |
| &lt;span class="gs"&gt;**API-first design**&lt;/span&gt; | ✅ Yes | Partial (read-only API) | Partial (read-only API) | ❌ No |
| &lt;span class="gs"&gt;**Python client**&lt;/span&gt; | ✅ Official | ❌ Community only | ❌ No | ❌ No |
| &lt;span class="gs"&gt;**Multi-framework single scan**&lt;/span&gt; | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Add-on cost |
| &lt;span class="gs"&gt;**Frameworks covered**&lt;/span&gt; | SOC2, GDPR, HIPAA, ISO 27001 | SOC2, ISO 27001, HIPAA + others | SOC2, ISO 27001, HIPAA + others | SOC2, ISO 27001, GDPR |
| &lt;span class="gs"&gt;**Audit-ready report generation**&lt;/span&gt; | ✅ Automated | ✅ Automated | ✅ Automated | ⚠️ Semi-manual |
| &lt;span class="gs"&gt;**GUI dashboard**&lt;/span&gt; | ✅ Yes | ✅ Polished | ✅ Polished | ✅ Yes |
| &lt;span class="gs"&gt;**Continuous monitoring**&lt;/span&gt; | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Scheduled scans |
| &lt;span class="gs"&gt;**Community/ecosystem**&lt;/span&gt; | Growing (GitHub-active) | Large, mature | Large, mature | Smaller |
| &lt;span class="gs"&gt;**Best for**&lt;/span&gt; | Dev-led teams, regulated infra | Sales-led compliance | Mid-market SaaS | SMBs, consultants |
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Deep Dive: What Each Tool Actually Does Well&lt;/span&gt;

&lt;span class="gu"&gt;### ComplianceWeave — Built for Teams Who Automate Everything&lt;/span&gt;

ComplianceWeave's core thesis is that compliance should live in your CI/CD pipeline, not in a browser tab someone checks quarterly. The API-first architecture isn't a checkbox feature — it means you can trigger compliance scans as part of a deployment gate, pull findings into your internal dashboards, or build custom alerting logic without waiting for a vendor to ship a native integration.

The Python client is genuinely useful. You can write something like:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from complianceweave import Scanner&lt;/p&gt;

&lt;p&gt;scanner = Scanner(frameworks=["SOC2", "HIPAA"])&lt;br&gt;
report = scanner.run(infrastructure="aws-prod")&lt;br&gt;
report.export("audit-2024-q3.pdf")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
...and have that living in a Makefile or GitHub Action. For teams that treat infrastructure as code, this fits naturally.

The self-hosted option is the other major differentiator. If you're in healthcare, financial services, or any regulated industry where sending infrastructure metadata to a third-party SaaS creates its own compliance problem — this matters enormously. Most competitors simply don't offer it.

**Where ComplianceWeave is weaker:** The ecosystem is younger. Integrations with niche SaaS tools (HR platforms, certain ticketing systems) are thinner than Vanta or Drata. The GUI, while functional, lacks the polished onboarding experience that makes Vanta so easy to hand to a non-technical compliance officer. Community resources — tutorials, pre-built policy templates, forum activity — are growing but not yet at the depth of the more established players.

---

### Vanta — The Safe Choice for Most Startups

Vanta built its reputation by making SOC2 feel achievable for early-stage companies. The onboarding experience is genuinely excellent — connect your AWS/GCP/Azure account, link your HR system, and within a day you have a live compliance dashboard. The GUI is polished enough that your Head of Sales can pull it up during a customer security review without embarrassment.

The partner network with auditing firms is a real advantage. Vanta has pre-negotiated relationships with auditors who know the platform, which can meaningfully compress your audit timeline.

**Where Vanta is weaker:** The per-employee pricing scales painfully for larger teams. The API is read-only, meaning you can *observe* your compliance posture programmatically but you can't *drive* it. If you want compliance embedded in your deployment pipeline rather than bolted on afterward, you'll be working around the tool rather than with it.

---

### Drata — Best-in-Class for Mid-Market

Drata targets the same space as Vanta but with more depth on the compliance workflow side — evidence collection, personnel training tracking, vendor risk management. For a 200-person company with a dedicated security team, Drata's additional process tooling earns its price.

**Where Drata is weaker:** Similar API limitations to Vanta. No self-hosting. Pricing is opaque until you talk to sales, which is a friction point for engineering-led evaluations.

---

### Tugboat Logic — The Consultant-Friendly Option

Tugboat Logic takes a more consultative approach, with strong support for teams that want human guidance through their first framework certification. If you're a small company doing SOC2 for the first time with no dedicated security staff, the guided approach has real value.

**Where Tugboat Logic is weaker:** Less automation depth, no continuous monitoring in the same sense as the others, and the multi-framework story requires add-on purchases.

---

## When to Use Each

**Choose ComplianceWeave if:**
- Your team treats infrastructure as code and wants compliance in the same mental model
- You're in a regulated industry where self-hosting isn't optional
- You need to cover multiple frameworks simultaneously without paying per-framework fees
- You want to build compliance checks into CI/CD pipelines, not just run them manually

**Choose Vanta if:**
- You're a startup doing your first SOC2 and want to move fast with minimal engineering overhead
- You have a non-technical compliance owner who needs a great GUI
- You value auditor relationships and want a streamlined path to certification

**Choose Drata if:**
- You're 100+ people and need compliance workflow management (training, vendor risk, personnel tracking) beyond just infrastructure scanning
- You have a dedicated security team that will get value from deeper process tooling

**Choose Tugboat Logic if:**
- You want guided, consultative support through your first certification
- Budget is a primary constraint and you're comfortable with more manual steps

---

## The Honest Bottom Line

None of these tools is universally best. Vanta and Drata win on polish, ecosystem maturity, and ease of onboarding for non-engineers. ComplianceWeave wins on programmability, self-hosting, and the ability to treat compliance as a first-class engineering concern rather than an annual fire drill.

The question worth asking your team: *Do you want a compliance dashboard, or do you want compliance infrastructure?* If it's the latter, ComplianceWeave's approach is architecturally different in ways that matter — not just a feature list difference, but a different philosophy about where compliance lives in your stack.

For teams that have already automated their security scanning, dependency auditing, and infrastructure provisioning, the idea of *not* being able to script your compliance checks will feel like a step backward. That's the team ComplianceWeave was built for.

---

*Pricing information and feature sets change frequently — verify current details directly with each vendor before making a purchasing decision. This comparison reflects publicly available information as of late 2024.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Track Data Pipeline Dependencies Automatically with DataLineage</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 08 Aug 2026 05:45:01 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-and</link>
      <guid>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-and</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stop&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Playing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Data&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Detective:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Let&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;DataLineage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Trace&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pipeline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Dependencies"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tutorial&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dbt&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Stop Playing Data Detective: Let DataLineage Trace Your Pipeline Dependencies&lt;/span&gt;

Picture this: it's 3pm on a Friday. Someone renamed a column in a source table. By Monday morning, three dashboards are broken, one Airflow DAG is throwing cryptic errors, and your Spark job silently swallowed bad nulls for 48 hours before anyone noticed.

You've been there. We've all been there.

The problem isn't that pipelines break — it's that when they break, you're essentially an archaeologist. You dig through dbt docs, grep through DAG definitions, and DM the person who "probably knows" what consumes that table. It's manual, it's slow, and it scales terribly.

This tutorial walks you through DataLineage — a tool that automatically maps dependencies across your entire stack (dbt, Airflow, Spark, custom ETL) so that when something changes, you know &lt;span class="ge"&gt;*exactly*&lt;/span&gt; what's downstream before it bites you.

Let's build something real.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## What We're Building&lt;/span&gt;

By the end of this post, you'll have a Python script that:
&lt;span class="p"&gt;
1.&lt;/span&gt; Traces the full dependency graph for any dataset
&lt;span class="p"&gt;2.&lt;/span&gt; Runs an impact analysis &lt;span class="ge"&gt;*before*&lt;/span&gt; a schema change ships
&lt;span class="p"&gt;3.&lt;/span&gt; Handles errors gracefully so your CI pipeline doesn't silently lie to you
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Prerequisites&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install requests python-dotenv&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Grab your API key from the DataLineage dashboard and store it safely:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;/p&gt;
&lt;h1&gt;
  
  
  .env
&lt;/h1&gt;

&lt;p&gt;DATALINEAGE_API_KEY=your_key_here&lt;br&gt;
DATALINEAGE_BASE_URL=&lt;a href="https://api.datalineage.io/v1" rel="noopener noreferrer"&gt;https://api.datalineage.io/v1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Step 1: Trace a Dataset's Dependency Graph

The first thing you'll want to do is ask DataLineage: *"who touches this dataset, and what does it touch?"*

We hit `POST /lineage/trace` with the dataset identifier — this can be a table name, a dbt model, or a Spark output path.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import os&lt;br&gt;
import requests&lt;br&gt;
from dotenv import load_dotenv&lt;/p&gt;

&lt;p&gt;load_dotenv()&lt;/p&gt;

&lt;p&gt;BASE_URL = os.getenv("DATALINEAGE_BASE_URL")&lt;br&gt;
HEADERS = {&lt;br&gt;
    "Authorization": f"Bearer {os.getenv('DATALINEAGE_API_KEY')}",&lt;br&gt;
    "Content-Type": "application/json",&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;def trace_lineage(dataset_id: str, depth: int = 3) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Initiate a lineage trace for a given dataset.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Args:
    dataset_id: The unique identifier for your dataset 
                (e.g., 'warehouse.analytics.user_events')
    depth: How many hops upstream/downstream to traverse

Returns:
    The trace job response containing a lineage ID
"""
payload = {
    "dataset_id": dataset_id,
    "depth": depth,
    "include_upstream": True,
    "include_downstream": True,
}

response = requests.post(
    f"{BASE_URL}/lineage/trace",
    json=payload,
    headers=HEADERS,
    timeout=30,
)

# Don't silently swallow HTTP errors — surface them immediately
response.raise_for_status()

return response.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  --- Run it ---
&lt;/h1&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    result = trace_lineage("warehouse.analytics.user_events")&lt;br&gt;
    print(f"Trace initiated. Lineage ID: {result['lineage_id']}")&lt;br&gt;
    print(f"Status: {result['status']}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Trace initiated. Lineage ID: lin_8f3a92bc&lt;br&gt;
Status: processing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; **Best practice:** Store `lineage_id` — you'll need it to fetch results and run impact analysis. Consider logging it to your observability stack alongside any schema migration you run.

---

## Step 2: Fetch the Full Lineage Graph

Tracing is async (these graphs can be large), so we poll `GET /lineage/{id}` until the job completes. Here's a polling wrapper that won't hammer the API:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import time&lt;/p&gt;

&lt;p&gt;def fetch_lineage(lineage_id: str, poll_interval: int = 2, max_wait: int = 60) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Poll for lineage results until complete or timeout.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Args:
    lineage_id: The ID returned from trace_lineage()
    poll_interval: Seconds between polls
    max_wait: Maximum seconds to wait before giving up

Returns:
    The complete lineage graph

Raises:
    TimeoutError: If the trace doesn't complete within max_wait
    RuntimeError: If the trace job failed on the server side
"""
elapsed = 0

while elapsed &amp;lt; max_wait:
    response = requests.get(
        f"{BASE_URL}/lineage/{lineage_id}",
        headers=HEADERS,
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    if data["status"] == "complete":
        return data

    if data["status"] == "failed":
        raise RuntimeError(
            f"Lineage trace failed: {data.get('error', 'Unknown error')}"
        )

    print(f"  Still processing... ({elapsed}s elapsed)")
    time.sleep(poll_interval)
    elapsed += poll_interval

raise TimeoutError(f"Lineage trace {lineage_id} did not complete within {max_wait}s")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def summarize_lineage(lineage_data: dict) -&amp;gt; None:&lt;br&gt;
    """Print a human-readable summary of the lineage graph."""&lt;br&gt;
    nodes = lineage_data.get("nodes", [])&lt;br&gt;
    edges = lineage_data.get("edges", [])&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(f"\n{'='*50}")
print(f"Lineage Graph: {lineage_data['dataset_id']}")
print(f"{'='*50}")
print(f"Total nodes: {len(nodes)}")
print(f"Total dependencies: {len(edges)}")

print("\nDownstream consumers:")
for node in nodes:
    if node["direction"] == "downstream":
        print(f"  [{node['tool']}] {node['name']}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  --- Run it ---
&lt;/h1&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    trace = trace_lineage("warehouse.analytics.user_events")&lt;br&gt;
    lineage = fetch_lineage(trace["lineage_id"])&lt;br&gt;
    summarize_lineage(lineage)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
  Still processing... (2s elapsed)&lt;/p&gt;

&lt;p&gt;==================================================&lt;/p&gt;
&lt;h1&gt;
  
  
  Lineage Graph: warehouse.analytics.user_events
&lt;/h1&gt;

&lt;p&gt;Total nodes: 14&lt;br&gt;
Total dependencies: 19&lt;/p&gt;

&lt;p&gt;Downstream consumers:&lt;br&gt;
  [dbt] model.analytics.weekly_retention&lt;br&gt;
  [dbt] model.analytics.revenue_attribution&lt;br&gt;&lt;br&gt;
  [airflow] dag.nightly_user_export&lt;br&gt;
  [spark] job.ml_feature_pipeline&lt;br&gt;
  [custom_etl] sync.salesforce_enrichment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Fourteen nodes. Nineteen edges. From a single table. This is exactly why manual tracing doesn't scale.

---

## Step 3: Run Impact Analysis Before a Schema Change

This is where DataLineage earns its keep. Before you rename that column, you ask: *"what breaks?"*

`POST /lineage/impact` takes your proposed change and returns a severity-ranked list of affected consumers.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
def analyze_impact(dataset_id: str, proposed_changes: list[dict]) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Assess the downstream impact of proposed schema changes.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Args:
    dataset_id: The dataset you're planning to modify
    proposed_changes: List of change descriptors
        Each dict should have: 'type' (rename/drop/type_change), 
        'field', and optionally 'new_name' or 'new_type'

Returns:
    Impact report with affected consumers ranked by severity
"""
payload = {
    "dataset_id": dataset_id,
    "changes": proposed_changes,
}

response = requests.post(
    f"{BASE_URL}/lineage/impact",
    json=payload,
    headers=HEADERS,
    timeout=30,
)
response.raise_for_status()
return response.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def print_impact_report(report: dict) -&amp;gt; None:&lt;br&gt;
    """Display a color-coded impact report (terminal-friendly)."""&lt;br&gt;
    severity_icons = {&lt;br&gt;
        "critical": "🔴",&lt;br&gt;
        "high":     "🟠", &lt;br&gt;
        "medium":   "🟡",&lt;br&gt;
        "low":      "🟢",&lt;br&gt;
    }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;affected = report.get("affected_consumers", [])

print(f"\n{'='*50}")
print(f"Impact Analysis Report")
print(f"{'='*50}")
print(f"Total affected consumers: {len(affected)}")

if not affected:
    print("✅ No downstream consumers affected. Safe to proceed.")
    return

for consumer in sorted(affected, key=lambda x: x["severity_rank"]):
    icon = severity_icons.get(consumer["severity"], "⚪")
    print(f"\n{icon} {consumer['name']}")
    print(f"   Tool: {consumer['tool']}")
    print(f"   Affected fields: {', '.join(consumer['affected_fields'])}")
    print(f"   Owner: {consumer.get('owner', 'Unknown')}")
    print(f"   Reason: {consumer['reason']}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  --- Run it ---
&lt;/h1&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    changes = [&lt;br&gt;
        {&lt;br&gt;
            "type": "rename",&lt;br&gt;
            "field": "user_id",&lt;br&gt;
            "new_name": "customer_id",&lt;br&gt;
        },&lt;br&gt;
        {&lt;br&gt;
            "type": "drop",&lt;br&gt;
            "field": "legacy_segment",&lt;br&gt;
        }&lt;br&gt;
    ]&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;report = analyze_impact("warehouse.analytics.user_events", changes)
print_impact_report(report)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  plaintext
&lt;/h1&gt;
&lt;h1&gt;
  
  
  Impact Analysis Report
&lt;/h1&gt;

&lt;p&gt;Total affected consumers: 6&lt;/p&gt;

&lt;p&gt;🔴 model.analytics.revenue_attribution&lt;br&gt;
   Tool: dbt&lt;br&gt;
   Affected fields: user_id, legacy_segment&lt;br&gt;
   Owner: &lt;a href="mailto:data-team@company.com"&gt;data-team@company.com&lt;/a&gt;&lt;br&gt;
   Reason: Direct field reference in JOIN condition&lt;/p&gt;

&lt;p&gt;🟠 dag.nightly_user_export&lt;br&gt;
   Tool: airflow&lt;br&gt;
   Affected fields: user_id&lt;br&gt;
   Owner: &lt;a href="mailto:platform-team@company.com"&gt;platform-team@company.com&lt;/a&gt;&lt;br&gt;
   Reason: Field used in SELECT and WHERE clause&lt;/p&gt;

&lt;p&gt;🟡 job.ml_feature_pipeline&lt;br&gt;
   Tool: spark&lt;br&gt;
   Affected fields: legacy_segment&lt;br&gt;
   Owner: &lt;a href="mailto:ml-team@company.com"&gt;ml-team@company.com&lt;/a&gt;&lt;br&gt;
   Reason: Feature derived from legacy_segment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now you have a contact list and a blast radius — before you've touched a single line of SQL.

---

## Putting It All Together

Here's a minimal CLI wrapper you can drop into your CI/CD pipeline as a pre-migration gate:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import sys&lt;/p&gt;

&lt;p&gt;def pre_migration_check(dataset_id: str, changes: list[dict]) -&amp;gt; int:&lt;br&gt;
    """&lt;br&gt;
    Returns exit code 0 if safe, 1 if critical impacts found.&lt;br&gt;
    Designed for use in CI pipelines.&lt;br&gt;
    """&lt;br&gt;
    print(f"Running pre-migration check for: {dataset_id}")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;report = analyze_impact(dataset_id, changes)
print_impact_report(report)

critical_count = sum(
    1 for c in report.get("affected_consumers", [])
    if c["severity"] == "critical"
)

if critical_count &amp;gt; 0:
    print(f"\n❌ {critical_count} critical impact(s) found. Resolve before proceeding.")
    return 1

print("\n✅ No critical impacts. Proceeding with migration.")
return 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    exit_code = pre_migration_check(&lt;br&gt;
        dataset_id="warehouse.analytics.user_events",&lt;br&gt;
        changes=[{"type": "rename", "field": "user_id", "new_name": "customer_id"}]&lt;br&gt;
    )&lt;br&gt;
    sys.exit(exit_code)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Add this to your GitHub Actions workflow before any migration step runs, and you've turned a Friday-afternoon fire drill into a boring, automated checklist item.

---

## Key Takeaways

- **Trace first, change second.** Running `POST /lineage/trace` before any schema work costs you 30 seconds and can save you hours.
- **Impact analysis is a contract.** Share the report with consumer team owners before you ship — it's a conversation starter, not just a debugging tool.
- **Automate the gate.** The pre-migration check pattern above is trivially embeddable in any CI system. Make it a required check.
- **Depth matters.** The `depth` parameter on trace is worth tuning — a depth of 2 might miss a dbt model that feeds a Spark job that feeds a dashboard.

Data dependencies are invisible until they're not. DataLineage makes them visible on purpose, before something goes wrong.

Now go rename that column — you've earned it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introducing DataLineage -- Automated Data Pipeline Lineage Tracking</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 08 Aug 2026 05:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/introducing-datalineage-automated-data-pipeline-lineage-tracking-14c5</link>
      <guid>https://dev.to/amoussa-eduhub/introducing-datalineage-automated-data-pipeline-lineage-tracking-14c5</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Schema&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Changed.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Congratulations,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You've&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Just&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Inherited&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;47&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Broken&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pipelines."&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;opensource&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dbt&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

It's 9:47 AM on a Tuesday. A product manager renames a column in a source table — &lt;span class="sb"&gt;`user_id`&lt;/span&gt; becomes &lt;span class="sb"&gt;`customer_id`&lt;/span&gt;, totally reasonable, five minutes of work. By 2 PM, three dashboards are blank, an ML feature pipeline is silently feeding stale data to a model in production, and your Slack is a graveyard of confused @ mentions.

You spend the next four hours playing archaeologist in your own infrastructure, grepping through dbt YAML files, reading Airflow DAG source code, and cross-referencing a Confluence page that was last updated in 2022. You find the broken consumers. Eventually. Most of them.

This is not a tooling problem that requires better documentation or more disciplined engineers. It's a &lt;span class="ge"&gt;*visibility*&lt;/span&gt; problem. And visibility problems have a specific kind of solution.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Lineage Gap Nobody Talks About&lt;/span&gt;

Data lineage isn't a new idea. Every modern data warehouse has &lt;span class="ge"&gt;*some*&lt;/span&gt; version of it. But there's a gap between "lineage that exists in one tool" and "lineage that reflects how your actual pipelines work."

Your dbt models know about each other. Your Airflow DAGs know about their own tasks. Your Spark jobs know about their inputs and outputs — if someone remembered to log them. But none of these tools talk to each other, which means when a schema change ripples &lt;span class="ge"&gt;*across*&lt;/span&gt; tool boundaries, you're flying blind.

That's the gap &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;DataLineage&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/datalineage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; was built to close.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## What DataLineage Actually Does&lt;/span&gt;

DataLineage runs as a lightweight service that connects to your existing stack — dbt, Airflow, Spark, and custom ETL — and builds a unified dependency graph across all of them. No manual configuration of relationships. No YAML files describing what you already know. It discovers the graph by reading what your tools already produce: dbt manifests, Airflow task metadata, Spark execution plans, and a thin SDK for anything custom.

The moment a schema changes, you query the graph and get back every downstream consumer, ranked by dependency depth, with the tool context preserved. You know &lt;span class="ge"&gt;*what*&lt;/span&gt; breaks, &lt;span class="ge"&gt;*where*&lt;/span&gt; it lives, and &lt;span class="ge"&gt;*how far*&lt;/span&gt; the blast radius extends.

Three things matter here:

&lt;span class="gs"&gt;**Auto-discovery, not auto-configuration.**&lt;/span&gt; You don't tell DataLineage about your pipelines. It reads your existing artifacts and infers the graph. Your dbt &lt;span class="sb"&gt;`manifest.json`&lt;/span&gt; already contains model dependencies. Your Airflow metadata database already contains task relationships. DataLineage connects the dots between them.

&lt;span class="gs"&gt;**Cross-tool lineage as a first-class feature.**&lt;/span&gt; A dbt model that feeds an Airflow DAG that triggers a Spark job that writes to a table consumed by three more dbt models — that full chain is visible as a single graph, not three disconnected fragments.

&lt;span class="gs"&gt;**Real-time impact analysis.**&lt;/span&gt; Before you rename that column, run an impact query. Get back the full list of affected consumers in under a second. Make the change knowing exactly what you're touching.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Quick Start&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install datalineage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from datalineage import LineageClient&lt;/p&gt;

&lt;p&gt;client = LineageClient(api_key="your_key")&lt;br&gt;
impact = client.impact_analysis(table="raw.events", column="user_id")&lt;br&gt;
print(impact.affected_nodes)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
That's the core loop. Point it at a table and column, get back a structured list of everything downstream. The `affected_nodes` list includes node type (dbt model, Airflow task, Spark job), tool context, and dependency depth.

---

## A Real-World Scenario: The Column Rename That Didn't Hurt

Let's say you're migrating your user identifier scheme. The source table `raw.users` currently has `legacy_user_id` and you're standardizing on `user_id`. You want to deprecate `legacy_user_id` eventually, but first you need to know who's still depending on it.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from datalineage import LineageClient&lt;br&gt;
from datalineage.models import ImpactReport&lt;/p&gt;

&lt;p&gt;client = LineageClient(api_key="your_key")&lt;/p&gt;
&lt;h1&gt;
  
  
  Get full impact report before touching anything
&lt;/h1&gt;

&lt;p&gt;report: ImpactReport = client.impact_analysis(&lt;br&gt;
    table="raw.users",&lt;br&gt;
    column="legacy_user_id",&lt;br&gt;
    depth=None  # traverse the full graph, no depth limit&lt;br&gt;
)&lt;/p&gt;
&lt;h1&gt;
  
  
  Group affected nodes by tool
&lt;/h1&gt;

&lt;p&gt;by_tool = report.group_by_tool()&lt;/p&gt;

&lt;p&gt;print(f"dbt models affected: {len(by_tool.get('dbt', []))}")&lt;br&gt;
print(f"Airflow DAGs affected: {len(by_tool.get('airflow', []))}")&lt;br&gt;
print(f"Spark jobs affected: {len(by_tool.get('spark', []))}")&lt;/p&gt;
&lt;h1&gt;
  
  
  Print the full dependency chain
&lt;/h1&gt;

&lt;p&gt;for node in report.affected_nodes:&lt;br&gt;
    print(f"[depth={node.depth}] {node.tool}/{node.name} → {node.owner_team}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Sample output:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
dbt models affected: 12&lt;br&gt;
Airflow DAGs affected: 3&lt;br&gt;
Spark jobs affected: 1&lt;/p&gt;

&lt;p&gt;[depth=1] dbt/stg_users → analytics-eng&lt;br&gt;
[depth=1] dbt/stg_user_events → analytics-eng&lt;br&gt;
[depth=2] dbt/fct_user_sessions → analytics-eng&lt;br&gt;
[depth=2] airflow/user_cohort_export → data-platform&lt;br&gt;
[depth=3] dbt/rpt_weekly_active_users → analytics-eng&lt;br&gt;
[depth=3] spark/user_feature_pipeline → ml-platform&lt;br&gt;
...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now you have a migration checklist. You know which teams to notify, in what order, and you can track remediation by querying the graph after each fix. When `affected_nodes` is empty, you're done.

This is the difference between a schema migration that takes a week of careful coordination and one that takes an afternoon.

---

## The API-First Design Decision

DataLineage exposes everything through a REST API with a Python client that wraps it. This wasn't an accident — it means the lineage graph is queryable from CI/CD pipelines, dbt hooks, Airflow sensors, or anywhere else you want to embed impact awareness.

A common pattern we've seen: add a DataLineage impact check as a pre-merge CI step for dbt PRs. If a PR modifies a model that has more than N downstream consumers, automatically request review from the teams that own those consumers. No more "I didn't know that model was used by the ML team."

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  In your CI pipeline
&lt;/h1&gt;

&lt;p&gt;import sys&lt;br&gt;
from datalineage import LineageClient&lt;/p&gt;

&lt;p&gt;client = LineageClient(api_key=os.environ["DATALINEAGE_KEY"])&lt;br&gt;
changed_models = get_changed_dbt_models()  # your CI helper&lt;/p&gt;

&lt;p&gt;for model in changed_models:&lt;br&gt;
    impact = client.impact_analysis(table=model)&lt;br&gt;
    if len(impact.affected_nodes) &amp;gt; 10:&lt;br&gt;
        print(f"⚠️  {model} affects {len(impact.affected_nodes)} downstream nodes")&lt;br&gt;
        print("Requesting cross-team review...")&lt;br&gt;
        sys.exit(1)  # block merge, require manual approval&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Where We Are

DataLineage is in public beta. The Python client is stable. The connectors for dbt, Airflow, and Spark are production-ready. We're actively working on Flink support and a graph visualization UI (because sometimes you need to *see* the graph, not just query it).

The API is free during beta with generous rate limits. We're not going to surprise you with a pricing page before you've had a chance to actually use the thing.

---

## Try It

If you've ever spent an afternoon debugging a broken pipeline that broke because of a change you didn't know existed, DataLineage was built for you.

- ⭐ **[Star us on GitHub](https://github.com/datalineage/datalineage)** — it helps more data engineers find the project
- 🔑 **[Get a free API key](https://datalineage.io/signup)** — beta access, no credit card
- 📖 **[Read the docs](https://docs.datalineage.io)** — including connector setup guides for dbt, Airflow, and Spark

We're in the DataLineage Discord if you have questions, run into issues, or want to tell us what connectors to build next. See you there.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ComplianceWeave vs Vanta, Drata, Secureframe: Which Compliance Automation Tool Should You Use?</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 01 Aug 2026 06:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-412h</link>
      <guid>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-412h</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compliance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tools&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2024:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Developer's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Honest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Field&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Guide"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Compliance Automation Tools in 2024: A Developer's Honest Field Guide&lt;/span&gt;

Let me tell you something nobody puts in their compliance tool landing page: &lt;span class="gs"&gt;**audits are boring in a very specific way**&lt;/span&gt;. Not the thrilling chaos of a production outage — the slow, grinding boredom of hunting down a screenshot of an access log from eight months ago at 11pm before a SOC2 review.

Compliance automation tools exist to make that particular flavor of suffering optional. But they're not all solving the same problem for the same person. This guide is written for developers and platform engineers who are being handed compliance ownership (congratulations, probably) and need to make a real decision.

I've tried to be genuinely fair here. Where a competitor is better, I'll say so.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Contenders&lt;/span&gt;

We're looking at &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; alongside three established players: &lt;span class="gs"&gt;**Vanta**&lt;/span&gt;, &lt;span class="gs"&gt;**Drata**&lt;/span&gt;, and &lt;span class="gs"&gt;**Tugboat Logic**&lt;/span&gt; (now part of OneTrust). These represent the mainstream of the compliance automation market.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Feature Comparison&lt;/span&gt;

| Feature | ComplianceWeave | Vanta | Drata | Tugboat Logic |
|---|---|---|---|---|
| SOC2 | ✅ | ✅ | ✅ | ✅ |
| GDPR | ✅ | Partial | ✅ | ✅ |
| HIPAA | ✅ | ✅ | ✅ | ✅ |
| ISO 27001 | ✅ | ✅ | ✅ | ✅ |
| Multi-framework single scan | ✅ | ❌ | ❌ | ❌ |
| API-first architecture | ✅ | ❌ | ❌ | ❌ |
| Self-hosted option | ✅ | ❌ | ❌ | ❌ |
| Python client | ✅ | Limited | ❌ | ❌ |
| GUI dashboard | ✅ | ✅ | ✅ | ✅ |
| Auditor portal | In roadmap | ✅ | ✅ | ✅ |
| Automated evidence collection | ✅ | ✅ | ✅ | ✅ |
| Pricing transparency | ✅ | ❌ | ❌ | ❌ |
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Deep Dive: Each Tool&lt;/span&gt;

&lt;span class="gu"&gt;### Vanta&lt;/span&gt;

Vanta is the market leader for a reason. Their integrations catalog is enormous — if you use a SaaS tool, Vanta probably connects to it. Their auditor-facing portal is polished and well-regarded by the actual humans who will sign off on your SOC2. If you're a startup that needs to close enterprise deals and wants the path of least resistance, Vanta is a defensible choice.

&lt;span class="gs"&gt;**Where it struggles:**&lt;/span&gt; Vanta is a GUI-first product. Automating evidence collection &lt;span class="ge"&gt;*into*&lt;/span&gt; your CI/CD pipeline or programmatically querying your compliance posture isn't really the use case they're optimizing for. Pricing is also opaque — expect a sales call before you see a number. For teams managing compliance across multiple frameworks simultaneously, you'll be running separate workflows.

&lt;span class="gu"&gt;### Drata&lt;/span&gt;

Drata competes closely with Vanta and has arguably better UX in some areas. Their continuous monitoring story is strong, and they've invested heavily in policy templates. Drata also has a more developer-friendly feel than Vanta, though it's still fundamentally a SaaS dashboard product.

&lt;span class="gs"&gt;**Where it struggles:**&lt;/span&gt; Like Vanta, there's no self-hosting, no real API-first story, and no Python client worth mentioning. If your compliance data sovereignty is a concern (regulated industries, government contracts), running Drata means trusting a third party with your infrastructure metadata.

&lt;span class="gu"&gt;### Tugboat Logic / OneTrust&lt;/span&gt;

Tugboat Logic was acquired by OneTrust and has evolved into an enterprise-grade GRC platform. If you're a larger organization that needs to map compliance into a broader risk management program, the OneTrust ecosystem is genuinely powerful.

&lt;span class="gs"&gt;**Where it struggles:**&lt;/span&gt; The acquisition brought enterprise complexity. Onboarding is slower, pricing is enterprise-tier, and the developer experience is an afterthought. For a 20-person engineering team that just needs SOC2 Type II, this is likely overkill.

&lt;span class="gu"&gt;### ComplianceWeave&lt;/span&gt;

ComplianceWeave takes a meaningfully different architectural bet: &lt;span class="gs"&gt;**compliance as code, not compliance as a dashboard**&lt;/span&gt;. The API-first design means you can trigger scans from a GitHub Action, pull results into your internal tooling, or build custom alerting on top of compliance drift. The Python client is a genuine first-class citizen, not a thin wrapper.

The multi-framework single scan is the feature I find most compelling. Running one scan that simultaneously evaluates against SOC2, GDPR, and ISO 27001 isn't just a time saver — it changes how you think about compliance. Overlapping controls become visible. You stop doing redundant work.

The self-hosted option matters more than it might seem. For companies in healthcare, finance, or defense contracting, sending infrastructure metadata to a third-party SaaS is a non-starter. ComplianceWeave gives you the option to keep that data inside your perimeter.

&lt;span class="gs"&gt;**Where it struggles:**&lt;/span&gt; The auditor-facing portal is still on the roadmap, which is a real gap. Vanta and Drata have spent years building relationships with auditing firms, and their portals make the auditor's job easier. ComplianceWeave's auto-generated reports are solid, but if your auditor is used to logging into a Vanta portal, there may be friction. Community and ecosystem are also smaller — fewer pre-built integrations, fewer Stack Overflow answers, fewer consultants who know the tool.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Pricing&lt;/span&gt;

Vanta, Drata, and Tugboat Logic all require sales conversations before you see pricing. Expect $10,000–$30,000/year for a typical startup depending on scope. ComplianceWeave publishes its pricing directly, which is itself a signal about who they're building for.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## When to Use Each&lt;/span&gt;

&lt;span class="gs"&gt;**Use Vanta if:**&lt;/span&gt; You're a Series A/B startup, you need SOC2 Type II to close enterprise deals in the next 6 months, you want the most auditor-recognized name on your report, and you're comfortable with a SaaS-only, GUI-first workflow.

&lt;span class="gs"&gt;**Use Drata if:**&lt;/span&gt; You want something similar to Vanta with slightly better UX, or you've had a specific recommendation from your auditing firm.

&lt;span class="gs"&gt;**Use Tugboat Logic / OneTrust if:**&lt;/span&gt; You're an enterprise with existing GRC programs, you need to map compliance into broader risk frameworks, and you have budget and implementation time to match.

&lt;span class="gs"&gt;**Use ComplianceWeave if:**&lt;/span&gt; You're an engineering-led team that wants compliance to live in your infrastructure-as-code workflow, not a separate SaaS dashboard. If you're managing multiple frameworks, need self-hosting for data sovereignty, or want to build compliance monitoring into your deployment pipeline programmatically — this is the tool designed for that use case. The smaller community is a real tradeoff, but the architectural philosophy is the right one for teams who treat compliance as an engineering problem.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Honest Summary&lt;/span&gt;

Most compliance tools are built for the &lt;span class="ge"&gt;*buyer*&lt;/span&gt; of compliance (the CISO, the VP of Sales who needs the SOC2 logo). ComplianceWeave is built for the &lt;span class="ge"&gt;*builder*&lt;/span&gt; of compliance — the engineer who has to actually implement and maintain it.

Neither approach is wrong. They're solving for different people in the same process.

Know which one you are, and pick accordingly.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="ge"&gt;*Have you used any of these tools in production? Drop your experience in the comments — especially if your auditor had opinions.*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Track Data Pipeline Dependencies Automatically with DataLineage</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 01 Aug 2026 05:45:01 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-38g6</link>
      <guid>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-38g6</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stop&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Playing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Detective:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Data&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lineage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tracing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Across&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Entire&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pipeline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Stack"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tutorial&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dataquality&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Stop Playing Detective: Automate Data Lineage Tracing Across Your Entire Pipeline Stack&lt;/span&gt;

You know the scene. A Slack message arrives at 9 AM: &lt;span class="ge"&gt;*"The revenue dashboard looks wrong."*&lt;/span&gt; You open your laptop and begin the archaeological dig — tracing data backward through Airflow DAGs, dbt models, Spark jobs, and three custom ETL scripts written by someone who left the company in 2022. Two hours later, you've found the culprit: a schema change in an upstream table that nobody knew had seventeen downstream consumers.

This tutorial will show you how to use &lt;span class="gs"&gt;**DataLineage**&lt;/span&gt; to make that investigation take thirty seconds instead of two hours.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## What We're Building&lt;/span&gt;

By the end of this tutorial, you'll have a Python script that:
&lt;span class="p"&gt;
1.&lt;/span&gt; Registers your pipeline assets with DataLineage
&lt;span class="p"&gt;2.&lt;/span&gt; Traces dependencies between them automatically
&lt;span class="p"&gt;3.&lt;/span&gt; Runs an impact analysis before any schema change ships

We'll simulate a realistic stack: an Airflow-ingested raw table, a dbt model that transforms it, and a Spark job that feeds a downstream dashboard.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Prerequisites&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install requests python-dotenv&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Set your API key in a `.env` file:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
conf&lt;br&gt;
DATALINEAGE_API_KEY=your_key_here&lt;br&gt;
DATALINEAGE_BASE_URL=&lt;a href="https://api.datalineage.io/v1" rel="noopener noreferrer"&gt;https://api.datalineage.io/v1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Step 1: Build a Reusable Client

Before touching the API, let's write a thin client wrapper. This keeps authentication and error handling in one place — a pattern your future self will thank you for.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import os&lt;br&gt;
import requests&lt;br&gt;
from dotenv import load_dotenv&lt;/p&gt;

&lt;p&gt;load_dotenv()&lt;/p&gt;

&lt;p&gt;class DataLineageClient:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self):&lt;br&gt;
        self.base_url = os.getenv("DATALINEAGE_BASE_URL")&lt;br&gt;
        self.headers = {&lt;br&gt;
            "Authorization": f"Bearer {os.getenv('DATALINEAGE_API_KEY')}",&lt;br&gt;
            "Content-Type": "application/json",&lt;br&gt;
        }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def _handle_response(self, response: requests.Response) -&amp;gt; dict:
    try:
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        error_body = response.json() if response.content else {}
        raise RuntimeError(
            f"API error {response.status_code}: "
            f"{error_body.get('message', str(e))}"
        ) from e
    except requests.exceptions.ConnectionError:
        raise RuntimeError("Could not reach DataLineage API. Check your network and base URL.")

def trace(self, payload: dict) -&amp;gt; dict:
    response = requests.post(
        f"{self.base_url}/lineage/trace",
        json=payload,
        headers=self.headers,
        timeout=10,
    )
    return self._handle_response(response)

def get_lineage(self, lineage_id: str) -&amp;gt; dict:
    response = requests.get(
        f"{self.base_url}/lineage/{lineage_id}",
        headers=self.headers,
        timeout=10,
    )
    return self._handle_response(response)

def impact_analysis(self, payload: dict) -&amp;gt; dict:
    response = requests.post(
        f"{self.base_url}/lineage/impact",
        json=payload,
        headers=self.headers,
        timeout=10,
    )
    return self._handle_response(response)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;client = DataLineageClient()&lt;br&gt;
print("Client initialized successfully.")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Client initialized successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Step 2: Register Your Pipeline Assets

Now let's tell DataLineage about our pipeline. We'll model three assets that represent a real-world ingestion → transformation → consumption chain.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
pipeline_assets = [&lt;br&gt;
    {&lt;br&gt;
        "asset_id": "raw.orders",&lt;br&gt;
        "asset_type": "table",&lt;br&gt;
        "tool": "airflow",&lt;br&gt;
        "schema": {&lt;br&gt;
            "columns": ["order_id", "customer_id", "amount", "created_at"],&lt;br&gt;
        },&lt;br&gt;
        "description": "Raw orders ingested from the transactional DB via Airflow.",&lt;br&gt;
    },&lt;br&gt;
    {&lt;br&gt;
        "asset_id": "dbt.orders_daily",&lt;br&gt;
        "asset_type": "model",&lt;br&gt;
        "tool": "dbt",&lt;br&gt;
        "schema": {&lt;br&gt;
            "columns": ["order_date", "customer_id", "total_amount", "order_count"],&lt;br&gt;
        },&lt;br&gt;
        "description": "Daily order aggregation built on raw.orders.",&lt;br&gt;
        "upstream": ["raw.orders"],&lt;br&gt;
    },&lt;br&gt;
    {&lt;br&gt;
        "asset_id": "spark.revenue_summary",&lt;br&gt;
        "asset_type": "dataset",&lt;br&gt;
        "tool": "spark",&lt;br&gt;
        "schema": {&lt;br&gt;
            "columns": ["week", "region", "revenue"],&lt;br&gt;
        },&lt;br&gt;
        "description": "Weekly revenue rollup consumed by the executive dashboard.",&lt;br&gt;
        "upstream": ["dbt.orders_daily"],&lt;br&gt;
    },&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;trace_result = client.trace({&lt;br&gt;
    "assets": pipeline_assets,&lt;br&gt;
    "auto_discover": True,&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;lineage_id = trace_result["lineage_id"]&lt;br&gt;
print(f"Lineage graph registered. ID: {lineage_id}")&lt;br&gt;
print(f"Assets discovered: {trace_result['asset_count']}")&lt;br&gt;
print(f"Edges mapped: {trace_result['edge_count']}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Lineage graph registered. ID: lin_8f3a92bc&lt;br&gt;
Assets discovered: 3&lt;br&gt;
Edges mapped: 2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The `auto_discover: true` flag tells DataLineage to also scan your connected integrations for any assets it can infer automatically — useful when you have undocumented dependencies lurking in legacy scripts.

---

## Step 3: Inspect the Full Lineage Graph

With the graph registered, let's pull it back and walk the dependency tree programmatically.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import json&lt;/p&gt;

&lt;p&gt;lineage = client.get_lineage(lineage_id)&lt;/p&gt;

&lt;p&gt;print("\n=== Lineage Graph ===\n")&lt;br&gt;
for node in lineage["nodes"]:&lt;br&gt;
    upstream_list = ", ".join(node.get("upstream", [])) or "None (source)"&lt;br&gt;
    print(f"  [{node['tool'].upper()}] {node['asset_id']}")&lt;br&gt;
    print(f"    └─ Upstream: {upstream_list}")&lt;br&gt;
    print(f"    └─ Columns:  {', '.join(node['schema']['columns'])}\n")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
=== Lineage Graph ===&lt;/p&gt;

&lt;p&gt;[AIRFLOW] raw.orders&lt;br&gt;
    └─ Upstream: None (source)&lt;br&gt;
    └─ Columns:  order_id, customer_id, amount, created_at&lt;/p&gt;

&lt;p&gt;[DBT] dbt.orders_daily&lt;br&gt;
    └─ Upstream: raw.orders&lt;br&gt;
    └─ Columns:  order_date, customer_id, total_amount, order_count&lt;/p&gt;

&lt;p&gt;[SPARK] spark.revenue_summary&lt;br&gt;
    └─ Upstream: dbt.orders_daily&lt;br&gt;
    └─ Columns:  week, region, revenue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This is the map you'd normally reconstruct manually from scattered YAML files and Slack threads.

---

## Step 4: Run Impact Analysis Before a Schema Change

Here's where DataLineage earns its keep. Before you rename `amount` to `order_amount` in `raw.orders`, let's see exactly what breaks.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
proposed_change = {&lt;br&gt;
    "asset_id": "raw.orders",&lt;br&gt;
    "change_type": "column_rename",&lt;br&gt;
    "details": {&lt;br&gt;
        "old_name": "amount",&lt;br&gt;
        "new_name": "order_amount",&lt;br&gt;
    },&lt;br&gt;
    "lineage_id": lineage_id,&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;impact = client.impact_analysis(proposed_change)&lt;/p&gt;

&lt;p&gt;print("\n=== Impact Analysis Report ===\n")&lt;br&gt;
print(f"Change: rename '{proposed_change['details']['old_name']}' "&lt;br&gt;
      f"→ '{proposed_change['details']['new_name']}' "&lt;br&gt;
      f"in {proposed_change['asset_id']}\n")&lt;/p&gt;

&lt;p&gt;if not impact["affected_assets"]:&lt;br&gt;
    print("✅ No downstream consumers affected. Safe to proceed.")&lt;br&gt;
else:&lt;br&gt;
    print(f"⚠️  {len(impact['affected_assets'])} downstream asset(s) affected:\n")&lt;br&gt;
    for asset in impact["affected_assets"]:&lt;br&gt;
        severity = asset.get("severity", "unknown").upper()&lt;br&gt;
        print(f"  [{severity}] {asset['asset_id']} ({asset['tool']})")&lt;br&gt;
        print(f"    Reason: {asset['reason']}")&lt;br&gt;
        print(f"    Suggested fix: {asset.get('suggested_fix', 'Manual review required')}\n")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
=== Impact Analysis Report ===&lt;/p&gt;

&lt;p&gt;Change: rename 'amount' → 'order_amount' in raw.orders&lt;/p&gt;

&lt;p&gt;⚠️  2 downstream asset(s) affected:&lt;/p&gt;

&lt;p&gt;[HIGH] dbt.orders_daily (dbt)&lt;br&gt;
    Reason: References column 'amount' in aggregation logic.&lt;br&gt;
    Suggested fix: Update SUM(amount) to SUM(order_amount) in orders_daily.sql&lt;/p&gt;

&lt;p&gt;[HIGH] spark.revenue_summary (spark)&lt;br&gt;
    Reason: Inherits 'amount' column through dbt.orders_daily transformation.&lt;br&gt;
    Suggested fix: Re-run dbt.orders_daily after fix; verify Spark job schema mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Two assets. Flagged. With suggested fixes. In under a second.

---

## Step 5: Wire It Into Your CI/CD Pipeline

The real power comes from making this check automatic. Here's a minimal GitHub Actions step that blocks a PR if an impact analysis returns high-severity hits:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  impact_gate.py — run this in CI before schema migrations ship
&lt;/h1&gt;

&lt;p&gt;import sys&lt;/p&gt;

&lt;p&gt;def check_impact_gate(lineage_id: str, asset_id: str, change: dict) -&amp;gt; None:&lt;br&gt;
    impact = client.impact_analysis({&lt;br&gt;
        "asset_id": asset_id,&lt;br&gt;
        "lineage_id": lineage_id,&lt;br&gt;
        **change,&lt;br&gt;
    })&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;high_severity = [
    a for a in impact.get("affected_assets", [])
    if a.get("severity") == "high"
]

if high_severity:
    print(f"❌ CI gate failed: {len(high_severity)} high-severity impact(s) detected.")
    for asset in high_severity:
        print(f"   - {asset['asset_id']}: {asset['reason']}")
    sys.exit(1)  # Fail the pipeline
else:
    print("✅ Impact gate passed. No high-severity consumers affected.")
    sys.exit(0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;check_impact_gate(&lt;br&gt;
    lineage_id=lineage_id,&lt;br&gt;
    asset_id="raw.orders",&lt;br&gt;
    change={"change_type": "column_rename", "details": {"old_name": "amount", "new_name": "order_amount"}},&lt;br&gt;
)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Drop this into a CI step with `python impact_gate.py` and schema changes can never silently break downstream consumers again.

---

## What You've Built

In about fifty lines of Python, you've replaced a two-hour manual investigation with an automated, CI-integrated lineage system that:

- **Maps** your full dbt + Airflow + Spark dependency graph
- **Surfaces** every downstream consumer before a breaking change ships
- **Blocks** high-risk schema changes at the PR level

The archaeological digs are over. Your 9 AM Slack messages just got a lot less stressful.

---

*Have a multi-tool pipeline with custom ETL? The `POST /lineage/trace` endpoint accepts a `custom_etl` asset type — drop your questions in the comments.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introducing DataLineage -- Automated Data Pipeline Lineage Tracking</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 01 Aug 2026 05:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/introducing-datalineage-automated-data-pipeline-lineage-tracking-34i6</link>
      <guid>https://dev.to/amoussa-eduhub/introducing-datalineage-automated-data-pipeline-lineage-tracking-34i6</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pipeline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lying&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(And&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Won't&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Know&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Until&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;It's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Too&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Late)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;opensource&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dbt&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

It's 2:47 AM. Your phone is buzzing. The ML model that drives 30% of your company's revenue recommendations is returning garbage. You SSH in, grep through logs, and eventually trace it back to a "harmless" column rename that happened three weeks ago in a Postgres table upstream. Three weeks. The damage has been compounding silently ever since.

You didn't break anything. You just didn't &lt;span class="ge"&gt;*know*&lt;/span&gt; what you'd break.

This is the dirty secret of modern data stacks: we've gotten incredibly good at building pipelines and remarkably bad at understanding them. We have dbt for transformation, Airflow for orchestration, Spark for scale, and a graveyard of custom ETL scripts held together with cron jobs and optimism. Each tool knows its own world. None of them talk to each other.

So when something changes upstream, you're not doing impact analysis. You're doing archaeology.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Introducing DataLineage&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;DataLineage&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/datalineage/datalineage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; automatically discovers and tracks data dependencies across your entire pipeline stack — dbt, Airflow, Spark, and custom ETL — without requiring you to annotate a single thing manually. When a schema changes, you see &lt;span class="ge"&gt;*every downstream consumer affected*&lt;/span&gt;, across tool boundaries, in real time.

Not a diagram you drew once and forgot to update. Not a wiki page from 2022. The actual, living dependency graph of your data.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Quick Start&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install datalineage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from datalineage import LineageClient&lt;/p&gt;

&lt;p&gt;client = LineageClient(api_key="your_key")&lt;br&gt;
impact = client.get_impact("schema.orders", change="rename_column", column="user_id")&lt;br&gt;
print(impact.affected_assets)  # Every downstream model, job, and feature that just broke&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
That's it. No YAML config. No agents to deploy. No "enterprise onboarding call."

DataLineage connects to your existing tools through their APIs and metadata stores — dbt's manifest, Airflow's DAG definitions, Spark's query history — and stitches the dependency graph together automatically.

---

## The Real-World Problem: Schema Changes Don't Respect Tool Boundaries

Here's a scenario that's more common than anyone admits.

You have a dbt model `fct_orders` that reads from a raw table `raw.orders`. That model feeds an Airflow DAG that trains a churn prediction model. That DAG writes features to a feature store. Those features power a Spark batch job that scores your entire user base nightly.

A data analyst renames `customer_id` to `user_id` in `raw.orders` because the naming is inconsistent with everything else. Totally reasonable. They check: does dbt compile? Yes. Does the dbt test pass? Yes (they updated the model). Ship it.

What they couldn't see: the Airflow DAG that bypasses dbt and reads `raw.orders` directly. The Spark job that joins on `customer_id` from a different source. The feature pipeline that's been hardcoding that column name for eight months.

Let's see how DataLineage handles this:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from datalineage import LineageClient&lt;br&gt;
from datalineage.models import SchemaChange, ChangeType&lt;/p&gt;

&lt;p&gt;client = LineageClient(api_key="your_key")&lt;/p&gt;
&lt;h1&gt;
  
  
  Register the proposed change before you make it
&lt;/h1&gt;

&lt;p&gt;change = SchemaChange(&lt;br&gt;
    asset="raw.orders",&lt;br&gt;
    change_type=ChangeType.RENAME_COLUMN,&lt;br&gt;
    before="customer_id",&lt;br&gt;
    after="user_id"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;report = client.analyze_impact(change)&lt;/p&gt;

&lt;p&gt;print(f"Direct consumers: {len(report.direct_consumers)}")&lt;br&gt;
print(f"Total affected assets: {len(report.all_affected)}")&lt;br&gt;
print(f"Critical path broken: {report.has_critical_path_impact}")&lt;/p&gt;

&lt;p&gt;for asset in report.all_affected:&lt;br&gt;
    print(f"  [{asset.tool}] {asset.name} — {asset.impact_type}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Output:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Direct consumers: 3&lt;br&gt;
Total affected assets: 11&lt;br&gt;
Critical path broken: True&lt;/p&gt;

&lt;p&gt;[dbt] fct_orders — BREAKING (column reference)&lt;br&gt;
  [airflow] dag:churn_model_training — BREAKING (direct SQL query)&lt;br&gt;
  [airflow] dag:weekly_cohort_report — INDIRECT (via fct_orders)&lt;br&gt;
  [spark] job:nightly_user_scoring — BREAKING (join key)&lt;br&gt;
  [dbt] dim_customers — INDIRECT (via fct_orders)&lt;br&gt;
  ... 6 more&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The analyst sees this *before* merging. Not three weeks later at 2:47 AM.

---

## How Auto-Discovery Actually Works

DataLineage doesn't ask you to declare dependencies. It finds them.

For **dbt**, it parses your compiled `manifest.json` and extracts the full ref() and source() graph — including column-level lineage where dbt exposes it.

For **Airflow**, it hooks into the metadata database and parses DAG definitions to extract SQL queries, dataset references, and task dependencies.

For **Spark**, it processes query execution logs and the Spark SQL query plan to reconstruct what read from what.

For **custom ETL**, you get a lightweight decorator:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from datalineage import track&lt;/p&gt;

&lt;p&gt;@track(reads=["raw.orders", "raw.products"], writes=["analytics.order_summary"])&lt;br&gt;
def run_custom_etl():&lt;br&gt;
    # Your existing code, untouched&lt;br&gt;
    ...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Everything flows into a unified graph. Cross-tool edges are first-class citizens, not afterthoughts.

---

## API-First, Because Your Stack Is Unique

Every data stack is a snowflake (the bad kind). DataLineage is built API-first so you can integrate it into your existing workflows rather than replacing them.

The Python client is the primary interface, but every operation is a REST call underneath. That means:

- **CI/CD integration**: Run impact analysis on every PR that touches schema definitions
- **Slack alerts**: Webhook when a breaking change is detected in a critical pipeline
- **dbt Cloud integration**: Trigger lineage refresh after every production job run
- **Custom dashboards**: Pull the graph data into whatever observability tool you already use

We're not trying to be your data catalog. We're trying to be the dependency engine that makes everything else smarter.

---

## What's Next

DataLineage is in public beta. What's working today:

- [x] dbt lineage (model + column level)
- [x] Airflow DAG parsing
- [x] Spark query log analysis
- [x] Real-time impact analysis API
- [x] Python client

On the roadmap:

- [ ] Fivetran + Airbyte source tracking
- [ ] GitHub PR integration (comment impact reports automatically)
- [ ] Column-level lineage across all tools
- [ ] Slack + PagerDuty alerting

---

## Try It

If you've ever spent more than an hour tracing a broken pipeline back to its source, DataLineage is for you.

**⭐ [Star us on GitHub](https://github.com/datalineage/datalineage)** — it genuinely helps us understand who's interested and what to build next.

**🚀 [Try the API](https://datalineage.io/signup)** — free tier includes up to 500 assets and unlimited impact analyses.

**💬 [Join our Discord](https://discord.gg/datalineage)** — we're actively building with early users. Your pipeline's weird edge case is exactly what we want to hear about.

The 2:47 AM call is optional. The broken pipeline is not. Let's fix the second one.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ComplianceWeave vs Vanta, Drata, Secureframe: Which Compliance Automation Tool Should You Use?</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 25 Jul 2026 06:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-i72</link>
      <guid>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-i72</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compliance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tools&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2024:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Developer's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Honest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Breakdown"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Compliance Automation Tools in 2024: A Developer's Honest Breakdown&lt;/span&gt;

Let me tell you something nobody in a vendor-written comparison will admit upfront: &lt;span class="gs"&gt;**most compliance automation tools were built for auditors, not engineers.**&lt;/span&gt; They assume you want to click through dashboards, export PDFs manually, and schedule calls with "compliance success managers."

That assumption shapes everything — the UX, the pricing model, the integration story.

This post tries to cut through that. I've looked at ComplianceWeave alongside the established players (Vanta, Drata, and Tugboat Logic) with one lens: &lt;span class="ge"&gt;*what does this actually feel like to operate as a developer or DevOps engineer responsible for compliance?*&lt;/span&gt;

Fair warning: I'll tell you when the alternatives are genuinely better. Spoiler — sometimes they are.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Landscape at a Glance&lt;/span&gt;

| | &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; | &lt;span class="gs"&gt;**Vanta**&lt;/span&gt; | &lt;span class="gs"&gt;**Drata**&lt;/span&gt; | &lt;span class="gs"&gt;**Tugboat Logic**&lt;/span&gt; |
|---|---|---|---|---|
| &lt;span class="gs"&gt;**Primary User**&lt;/span&gt; | Developer / DevOps | GRC / Founder | GRC / Founder | GRC Manager |
| &lt;span class="gs"&gt;**API Access**&lt;/span&gt; | First-class (full REST + Python client) | Limited (read-mostly) | Limited | Minimal |
| &lt;span class="gs"&gt;**Self-Hosted**&lt;/span&gt; | ✅ Yes | ❌ No | ❌ No | ❌ No |
| &lt;span class="gs"&gt;**Frameworks**&lt;/span&gt; | SOC2, GDPR, HIPAA, ISO 27001 (one scan) | SOC2, HIPAA, ISO 27001 (separate) | SOC2, HIPAA, ISO 27001 (separate) | SOC2, ISO 27001 |
| &lt;span class="gs"&gt;**Multi-Framework Scan**&lt;/span&gt; | ✅ Single scan, mapped across | ❌ Per-framework runs | ❌ Per-framework runs | ❌ Per-framework runs |
| &lt;span class="gs"&gt;**Audit-Ready Reports**&lt;/span&gt; | Auto-generated | Semi-automated | Semi-automated | Manual assembly |
| &lt;span class="gs"&gt;**Pricing Model**&lt;/span&gt; | Usage-based / self-hosted | Per-seat + integrations | Per-seat + integrations | Per-user |
| &lt;span class="gs"&gt;**Community / OSS**&lt;/span&gt; | Growing (GitHub presence) | Large (partner ecosystem) | Large (partner ecosystem) | Small |
| &lt;span class="gs"&gt;**Ease of Setup**&lt;/span&gt; | Moderate (requires config) | Very easy | Very easy | Moderate |
| &lt;span class="gs"&gt;**Best For**&lt;/span&gt; | Infra-heavy teams, CI/CD integration | Early-stage startups | Mid-market SaaS | Enterprise GRC |
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Feature Deep Dive&lt;/span&gt;

&lt;span class="gu"&gt;### ComplianceWeave&lt;/span&gt;

The architectural bet here is interesting: &lt;span class="gs"&gt;**API-first**&lt;/span&gt; means compliance checks can live inside your existing pipelines. You can trigger a SOC2 evidence collection run from a GitHub Action. You can query your current control status from a Slack bot. You can diff your compliance posture between last Tuesday and today.

The multi-framework scan is genuinely useful — if you're pursuing SOC2 &lt;span class="ge"&gt;*and*&lt;/span&gt; GDPR simultaneously (common for companies with EU customers), you're not running two separate tooling stacks and reconciling overlapping controls by hand. ComplianceWeave maps shared controls once.

The self-hosted option matters for two audiences: companies with strict data residency requirements, and security-conscious teams who simply don't want their infrastructure evidence sitting in a third-party SaaS. That's a real concern, not paranoia.

&lt;span class="gs"&gt;**Where it falls short:**&lt;/span&gt; The setup experience requires more configuration than the SaaS alternatives. If you want something running in 30 minutes with zero engineering involvement, this isn't it. The community is also younger — fewer pre-built integrations and less Stack Overflow-style tribal knowledge floating around.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Vanta&lt;/span&gt;

Vanta's strength is &lt;span class="gs"&gt;**time to value for non-technical founders.**&lt;/span&gt; Connect your AWS account, your GitHub, your HR system — and you have a live compliance dashboard in under an hour. The partner network (auditors who know Vanta's export format) is genuinely valuable when you're approaching your first SOC2 audit.

The tradeoff: you're in a walled garden. The API is read-mostly and not designed for automation. You can't easily pull Vanta data into your own dashboards or trigger checks programmatically. For a developer who wants compliance as code, it feels like a detour.

&lt;span class="gs"&gt;**Vanta is the right call if:**&lt;/span&gt; You're a non-technical founder or early-stage startup that needs SOC2 quickly and doesn't have engineering cycles to spare on tooling configuration.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Drata&lt;/span&gt;

Drata sits in similar territory to Vanta but with slightly more polish on the continuous monitoring story and a stronger mid-market positioning. The evidence collection automation is solid, and their control mapping is well-maintained.

Like Vanta, the API surface is limited. Drata is also GUI-first in a way that feels intentional — the product is designed around the assumption that a compliance manager, not an engineer, is the daily user.

&lt;span class="gs"&gt;**Drata is the right call if:**&lt;/span&gt; You're a mid-market SaaS company with a dedicated GRC or security person who will own the tool day-to-day.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Tugboat Logic&lt;/span&gt;

Tugboat Logic (now part of OneTrust) leans hardest into the enterprise GRC buyer. The policy management features are more mature, and the workflow tooling for getting controls reviewed and approved across large organizations is better than the others listed here.

The developer experience is the weakest of the four. This is a tool built for compliance teams, full stop.

&lt;span class="gs"&gt;**Tugboat Logic is the right call if:**&lt;/span&gt; You're in a larger organization where compliance is owned by a dedicated GRC team and the engineering team's role is answering requests, not running the tooling.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Pricing: What We Know&lt;/span&gt;

Pricing in this space is famously opaque. Here's the honest summary:
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Vanta and Drata**&lt;/span&gt; both use per-seat + integration pricing that scales quickly. Expect $10K–$30K/year for a typical Series A startup, more as you add frameworks.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Tugboat Logic**&lt;/span&gt; is enterprise-priced and typically requires a sales conversation.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; uses usage-based pricing with a self-hosted tier that can dramatically reduce cost for teams with the infrastructure to run it.

If cost is a primary driver and you have engineering resources, ComplianceWeave's self-hosted path is worth evaluating seriously.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Community and Ecosystem&lt;/span&gt;

This is where the established players have a real edge. Vanta and Drata have large auditor partner networks, active user communities, and years of accumulated documentation and workarounds. When you hit an edge case at 11pm before your audit, someone has probably already solved it.

ComplianceWeave's community is smaller but growing, and the API-first design means integrations are more composable — you're not waiting for a vendor to build the Datadog connector.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## When to Use Each&lt;/span&gt;

&lt;span class="gs"&gt;**Use ComplianceWeave when:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You want compliance integrated into CI/CD pipelines, not managed separately
&lt;span class="p"&gt;-&lt;/span&gt; You're pursuing multiple frameworks simultaneously
&lt;span class="p"&gt;-&lt;/span&gt; Data residency or security requirements make SaaS evidence storage a concern
&lt;span class="p"&gt;-&lt;/span&gt; You have engineering resources and want to treat compliance as infrastructure

&lt;span class="gs"&gt;**Use Vanta when:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You need SOC2 quickly with minimal engineering involvement
&lt;span class="p"&gt;-&lt;/span&gt; You're pre-Series A and speed matters more than flexibility
&lt;span class="p"&gt;-&lt;/span&gt; You'll be working closely with a Vanta-familiar auditor

&lt;span class="gs"&gt;**Use Drata when:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You have a dedicated GRC or security hire who will own the tool
&lt;span class="p"&gt;-&lt;/span&gt; You want strong continuous monitoring with a polished GUI
&lt;span class="p"&gt;-&lt;/span&gt; You're mid-market SaaS with standard cloud infrastructure

&lt;span class="gs"&gt;**Use Tugboat Logic when:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Compliance is owned by a dedicated enterprise GRC team
&lt;span class="p"&gt;-&lt;/span&gt; Policy management and approval workflows matter as much as technical controls
&lt;span class="p"&gt;-&lt;/span&gt; You're already in the OneTrust ecosystem
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Honest Conclusion&lt;/span&gt;

There's no universally best tool here. The right answer depends almost entirely on &lt;span class="ge"&gt;*who in your organization owns compliance*&lt;/span&gt; and &lt;span class="ge"&gt;*how tightly you want it integrated with your engineering workflow.*&lt;/span&gt;

The interesting thing about ComplianceWeave is that it's making a different bet than the incumbents — that compliance should be code, not a SaaS dashboard your engineers file tickets into. If that bet resonates with how your team works, it's worth a serious look. If it doesn't, Vanta and Drata have earned their market position for good reasons.

Pick the tool that fits your team's actual workflow, not the one with the best demo.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>DataLineage vs OpenLineage, Marquez, DataHub: Which Data Lineage Tool Should You Use?</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 25 Jul 2026 05:45:04 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/datalineage-vs-openlineage-marquez-datahub-which-data-lineage-tool-should-you-use-5f7m</link>
      <guid>https://dev.to/amoussa-eduhub/datalineage-vs-openlineage-marquez-datahub-which-data-lineage-tool-should-you-use-5f7m</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lineage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tools&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2024:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;An&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Honest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Field&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Guide&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(With&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Scars&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Prove&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;It)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dataquality&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;opensource&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Data Lineage Tools in 2024: An Honest Field Guide (With Scars to Prove It)&lt;/span&gt;

There's a specific kind of pain that data engineers know intimately: a schema changes upstream, something breaks downstream, and you spend three hours playing archaeological detective through Slack threads and stale Confluence docs to understand &lt;span class="ge"&gt;*why*&lt;/span&gt;.

Data lineage tools exist to prevent exactly that. But the space is crowded, the marketing is loud, and "automatic" means something different on every vendor's website. This post is my attempt at a genuinely fair comparison — the kind I wish existed when I was evaluating these tools.

I'll cover &lt;span class="gs"&gt;**DataLineage**&lt;/span&gt;, &lt;span class="gs"&gt;**OpenMetadata**&lt;/span&gt;, &lt;span class="gs"&gt;**Marquez**&lt;/span&gt;, and &lt;span class="gs"&gt;**Atlan**&lt;/span&gt;. Four tools with meaningfully different philosophies. Let's get into it.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Core Problem Each Tool Is Trying to Solve&lt;/span&gt;

Before the table, a quick framing. These tools aren't identical products competing for the same user — they have distinct centers of gravity:
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**DataLineage**&lt;/span&gt; is laser-focused on &lt;span class="ge"&gt;*pipeline impact analysis*&lt;/span&gt; — specifically, "what breaks if I change this?"
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**OpenMetadata**&lt;/span&gt; is a full data catalog that includes lineage as one feature among many
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Marquez**&lt;/span&gt; is an open standard and metadata server built around the OpenLineage spec
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Atlan**&lt;/span&gt; is an enterprise data catalog with strong governance features and lineage visualization

Understanding this helps you pick the right tool rather than the most-hyped one.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Comparison Table&lt;/span&gt;

| Dimension | DataLineage | OpenMetadata | Marquez | Atlan |
|---|---|---|---|---|
| &lt;span class="gs"&gt;**Setup complexity**&lt;/span&gt; | Low (zero-config discovery) | Medium (connectors + config) | Medium (instrumentation required) | High (enterprise onboarding) |
| &lt;span class="gs"&gt;**Auto-discovery**&lt;/span&gt; | ✅ Yes | ⚠️ Partial (connector-dependent) | ❌ Requires OpenLineage instrumentation | ⚠️ Partial (crawler-based) |
| &lt;span class="gs"&gt;**dbt support**&lt;/span&gt; | ✅ Native | ✅ Native | ✅ Via OpenLineage | ✅ Native |
| &lt;span class="gs"&gt;**Airflow support**&lt;/span&gt; | ✅ Native | ✅ Native | ✅ Via provider | ✅ Native |
| &lt;span class="gs"&gt;**Spark support**&lt;/span&gt; | ✅ Native | ⚠️ Limited | ✅ Via listener | ⚠️ Limited |
| &lt;span class="gs"&gt;**Custom ETL support**&lt;/span&gt; | ✅ Yes | ❌ Manual only | ⚠️ Requires SDK | ❌ Manual only |
| &lt;span class="gs"&gt;**Impact analysis API**&lt;/span&gt; | ✅ Dedicated endpoint | ❌ | ❌ | ⚠️ UI only |
| &lt;span class="gs"&gt;**Data catalog features**&lt;/span&gt; | ❌ Not the focus | ✅ Full catalog | ❌ Lineage only | ✅ Full catalog |
| &lt;span class="gs"&gt;**Governance / RBAC**&lt;/span&gt; | ⚠️ Basic | ✅ Strong | ❌ | ✅ Enterprise-grade |
| &lt;span class="gs"&gt;**License**&lt;/span&gt; | BSL 1.1 (free non-prod) | Apache 2.0 | Apache 2.0 | Proprietary SaaS |
| &lt;span class="gs"&gt;**Self-hosted option**&lt;/span&gt; | ✅ | ✅ | ✅ | ❌ |
| &lt;span class="gs"&gt;**Community size**&lt;/span&gt; | Small / growing | Large | Medium | Vendor-driven |
| &lt;span class="gs"&gt;**Pricing (prod)**&lt;/span&gt; | Paid (contact) | Free (self-host) | Free (self-host) | Expensive (enterprise) |
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Honest Takes, Tool by Tool&lt;/span&gt;

&lt;span class="gu"&gt;### DataLineage&lt;/span&gt;

&lt;span class="gs"&gt;**What it does well:**&lt;/span&gt; The zero-config auto-discovery claim holds up better than most. Rather than requiring you to annotate your pipelines or instrument your code, DataLineage parses your existing dbt manifests, Airflow DAG structure, and Spark query plans to build a dependency graph automatically. For teams with messy, organically grown pipelines — which is most teams — this is genuinely valuable.

The impact analysis endpoint is the feature that makes engineers' eyes light up. You can query it programmatically: "if column &lt;span class="sb"&gt;`user_id`&lt;/span&gt; in &lt;span class="sb"&gt;`raw.events`&lt;/span&gt; changes type, what downstream models and dashboards are affected?" This is CI/CD-friendly in a way that most competitors aren't.

&lt;span class="gs"&gt;**Where it falls short:**&lt;/span&gt; DataLineage is not a data catalog. If you need column-level business glossary, data quality scoring, or access governance, you'll need another tool. The community is also small — don't expect a rich ecosystem of plugins or a busy Slack community yet. The BSL 1.1 license is worth reading carefully; it's free for non-production use, but production deployments require a commercial license, which puts it in a different budget conversation than Apache-licensed alternatives.

&lt;span class="gs"&gt;**Best for:**&lt;/span&gt; Data engineering teams who want fast time-to-value on lineage specifically, and who are running heterogeneous stacks.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### OpenMetadata&lt;/span&gt;

&lt;span class="gs"&gt;**What it does well:**&lt;/span&gt; OpenMetadata is probably the most complete open-source data catalog available right now. Lineage is one well-implemented feature inside a broader platform that includes data quality, profiling, glossary, and RBAC. If you need a single pane of glass for your data assets, it's a serious contender. The community is active and the connector library is extensive.

&lt;span class="gs"&gt;**Where it falls short:**&lt;/span&gt; Setup is not trivial. You're deploying a multi-service application, and getting lineage working well requires configuring connectors for each source. Auto-discovery is connector-dependent — if your ETL is custom Python scripts, you're writing manual lineage. There's no dedicated impact analysis API; lineage is primarily a visual exploration tool.

&lt;span class="gs"&gt;**Best for:**&lt;/span&gt; Teams who need a full data catalog and are willing to invest in setup. Especially strong if you have a dedicated data platform team.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Marquez&lt;/span&gt;

&lt;span class="gs"&gt;**What it does well:**&lt;/span&gt; Marquez is the reference implementation of the OpenLineage specification — an open standard for lineage metadata. If you care about vendor neutrality and interoperability, Marquez is philosophically appealing. It's lightweight, Apache-licensed, and the OpenLineage spec has solid adoption across the ecosystem.

&lt;span class="gs"&gt;**Where it falls short:**&lt;/span&gt; Marquez requires instrumentation. Your pipelines need to emit OpenLineage events, which means adding providers or listeners to Airflow, Spark, etc. For legacy or custom pipelines, this is real engineering work. The UI is functional but minimal. Think of it as infrastructure, not a product.

&lt;span class="gs"&gt;**Best for:**&lt;/span&gt; Teams building a custom lineage solution who want a standards-based backend. Also good if you're already heavily invested in the OpenLineage ecosystem.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Atlan&lt;/span&gt;

&lt;span class="gs"&gt;**What it does well:**&lt;/span&gt; Atlan is the enterprise choice — polished UI, strong governance features, Slack/Jira integrations, and a sales team that will hold your hand through onboarding. Lineage visualization is excellent. If budget isn't a constraint and you need executive-friendly dashboards, Atlan delivers.

&lt;span class="gs"&gt;**Where it falls short:**&lt;/span&gt; It's expensive, it's SaaS-only (no self-hosting), and the pricing is opaque. Auto-discovery is crawler-based and less comprehensive than DataLineage's approach for complex pipeline stacks. Impact analysis is UI-driven, not API-driven, which limits automation use cases.

&lt;span class="gs"&gt;**Best for:**&lt;/span&gt; Enterprise data teams with governance requirements, compliance needs, and budget to match.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## When to Use Each: The Decision Tree&lt;/span&gt;

&lt;span class="gs"&gt;**Choose DataLineage if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You need lineage working &lt;span class="ge"&gt;*fast*&lt;/span&gt; without a large setup investment
&lt;span class="p"&gt;-&lt;/span&gt; Your stack is heterogeneous (dbt + Airflow + Spark + custom scripts)
&lt;span class="p"&gt;-&lt;/span&gt; You want to integrate impact analysis into your CI/CD pipeline programmatically
&lt;span class="p"&gt;-&lt;/span&gt; You're a startup or scale-up that doesn't need a full catalog yet

&lt;span class="gs"&gt;**Choose OpenMetadata if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You need a full data catalog, not just lineage
&lt;span class="p"&gt;-&lt;/span&gt; You have a dedicated data platform team to manage it
&lt;span class="p"&gt;-&lt;/span&gt; Open-source and self-hosted is a hard requirement
&lt;span class="p"&gt;-&lt;/span&gt; Community and plugin ecosystem matter to you

&lt;span class="gs"&gt;**Choose Marquez if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You're building a custom metadata platform and want a standards-based foundation
&lt;span class="p"&gt;-&lt;/span&gt; Your team already uses OpenLineage-compatible tools
&lt;span class="p"&gt;-&lt;/span&gt; You want maximum flexibility and don't need a polished UI

&lt;span class="gs"&gt;**Choose Atlan if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You're in an enterprise environment with compliance and governance requirements
&lt;span class="p"&gt;-&lt;/span&gt; Budget is not the primary constraint
&lt;span class="p"&gt;-&lt;/span&gt; You need a tool your non-technical stakeholders can actually use
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Final Thought&lt;/span&gt;

The "best" data lineage tool is the one your team will actually maintain. A zero-config tool with 80% coverage that's running in production beats a perfectly configured tool that's been in "evaluation" for six months.

Start with your most painful problem — broken pipelines, schema drift, compliance audits — and work backward to the tool that solves it most directly. All four tools here solve real problems. None of them solves all of them.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="ge"&gt;*Have experience with any of these tools? Corrections, additions, or war stories welcome in the comments.*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Track Data Pipeline Dependencies Automatically with DataLineage</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 25 Jul 2026 05:45:03 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-4co2</link>
      <guid>https://dev.to/amoussa-eduhub/how-to-track-data-pipeline-dependencies-automatically-with-datalineage-4co2</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Pipeline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lying&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(And&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Here's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;How&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Catch&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;It)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;dataengineering&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tutorial&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dataquality&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Your Pipeline is Lying to You (And Here's How to Catch It)&lt;/span&gt;

Last Tuesday at 2 AM, a Slack message woke up a data engineer somewhere. A dashboard was broken. The on-call scrambled through dbt models, Airflow DAGs, and three Spark jobs trying to answer one question: &lt;span class="ge"&gt;*who touched what?*&lt;/span&gt;

Four hours later, they found it. A column rename. Innocent. Undocumented.

This tutorial is about never having that 2 AM call again.

We'll use &lt;span class="gs"&gt;**DataLineage**&lt;/span&gt; — a tool that automatically maps dependencies across your entire pipeline stack — to build a system that &lt;span class="ge"&gt;*knows*&lt;/span&gt; what breaks before you deploy the thing that breaks it.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## What We're Actually Building&lt;/span&gt;

By the end of this post, you'll have a Python workflow that:
&lt;span class="p"&gt;
1.&lt;/span&gt; Traces a schema change through your entire pipeline
&lt;span class="p"&gt;2.&lt;/span&gt; Identifies every downstream consumer affected
&lt;span class="p"&gt;3.&lt;/span&gt; Runs an impact assessment &lt;span class="ge"&gt;*before*&lt;/span&gt; you merge that PR

No more archaeological digs through YAML files at midnight.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Prerequisites&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install requests python-dotenv&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
You'll need a DataLineage API key. Set it in a `.env` file:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
properties&lt;br&gt;
DATALINEAGE_API_KEY=your_key_here&lt;br&gt;
DATALINEAGE_BASE_URL=&lt;a href="https://api.datalineage.io/v1" rel="noopener noreferrer"&gt;https://api.datalineage.io/v1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Let's write a small client wrapper we'll reuse throughout:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import os&lt;br&gt;
import requests&lt;br&gt;
from dotenv import load_dotenv&lt;/p&gt;

&lt;p&gt;load_dotenv()&lt;/p&gt;

&lt;p&gt;class DataLineageClient:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self):&lt;br&gt;
        self.base_url = os.getenv("DATALINEAGE_BASE_URL")&lt;br&gt;
        self.headers = {&lt;br&gt;
            "Authorization": f"Bearer {os.getenv('DATALINEAGE_API_KEY')}",&lt;br&gt;
            "Content-Type": "application/json"&lt;br&gt;
        }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def _handle_response(self, response: requests.Response) -&amp;gt; dict:
    """Centralized error handling — because silent failures are the worst kind."""
    try:
        response.raise_for_status()
    except requests.exceptions.HTTPError as e:
        error_body = response.json().get("error", "No error detail provided")
        raise RuntimeError(
            f"DataLineage API error [{response.status_code}]: {error_body}"
        ) from e
    return response.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; **Best practice:** Always surface the API's error message, not just the status code. "422" tells you nothing. "Column 'user_id' not found in registered schema" tells you everything.

---

## Step 1: Trace a Node Through the Pipeline

Every table, model, or dataset in DataLineage is a **node**. When you want to understand a node's full family tree — what it depends on, what depends on it — you call `POST /lineage/trace`.

Let's trace our `orders` dbt model:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
def trace_lineage(client: DataLineageClient, node_id: str, depth: int = 3) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Trace upstream and downstream dependencies for a given node.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Args:
    node_id: The unique identifier for your table/model/dataset
    depth:   How many hops to traverse (default 3 is usually enough)
"""
payload = {
    "node_id": node_id,
    "depth": depth,
    "include_metadata": True  # Grab schema info, owner, last modified
}

response = client._handle_response(
    requests.post(
        f"{client.base_url}/lineage/trace",
        json=payload,
        headers=client.headers
    )
)
return response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Run it
&lt;/h1&gt;

&lt;p&gt;client = DataLineageClient()&lt;br&gt;
lineage = trace_lineage(client, node_id="dbt.production.orders")&lt;/p&gt;

&lt;p&gt;print(f"Node: {lineage['node']['name']}")&lt;br&gt;
print(f"Upstream dependencies: {len(lineage['upstream'])}")&lt;br&gt;
print(f"Downstream consumers:  {len(lineage['downstream'])}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
Node: dbt.production.orders&lt;br&gt;
Upstream dependencies: 4&lt;br&gt;
Downstream consumers:  11&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Eleven downstream consumers. That's eleven things that could break if someone renames a column. Let's see exactly what they are.

---

## Step 2: Retrieve and Parse the Full Lineage Graph

The trace job runs asynchronously for large graphs. Use the returned `lineage_id` to fetch results:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import time&lt;/p&gt;

&lt;p&gt;def get_lineage_result(client: DataLineageClient, lineage_id: str, timeout: int = 30) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Poll for lineage results with a timeout.&lt;br&gt;
    Large graphs can take a few seconds to compute.&lt;br&gt;
    """&lt;br&gt;
    deadline = time.time() + timeout&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while time.time() &amp;lt; deadline:
    response = client._handle_response(
        requests.get(
            f"{client.base_url}/lineage/{lineage_id}",
            headers=client.headers
        )
    )

    status = response.get("status")

    if status == "complete":
        return response["graph"]
    elif status == "failed":
        raise RuntimeError(f"Lineage computation failed: {response.get('reason')}")

    # Still processing — wait and retry
    time.sleep(2)

raise TimeoutError(f"Lineage graph not ready after {timeout}s. Try increasing timeout.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def print_dependency_tree(graph: dict) -&amp;gt; None:&lt;br&gt;
    """Human-readable summary of what we found."""&lt;br&gt;
    print("\n📊 LINEAGE SUMMARY")&lt;br&gt;
    print("=" * 50)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print("\n⬆️  UPSTREAM (this node depends on):")
for node in graph.get("upstream", []):
    tool = node["metadata"].get("tool", "unknown")
    print(f"  └─ [{tool.upper()}] {node['name']}")

print("\n⬇️  DOWNSTREAM (depends on this node):")
for node in graph.get("downstream", []):
    tool = node["metadata"].get("tool", "unknown")
    owner = node["metadata"].get("owner", "unassigned")
    print(f"  └─ [{tool.upper()}] {node['name']}  (owner: {owner})")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Fetch and display
&lt;/h1&gt;

&lt;p&gt;lineage_id = lineage["lineage_id"]&lt;br&gt;
graph = get_lineage_result(client, lineage_id)&lt;br&gt;
print_dependency_tree(graph)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h1&gt;
  
  
  📊 LINEAGE SUMMARY
&lt;/h1&gt;

&lt;p&gt;⬆️  UPSTREAM (this node depends on):&lt;br&gt;
  └─ [DBT] dbt.production.raw_orders&lt;br&gt;
  └─ [DBT] dbt.production.customers&lt;br&gt;
  └─ [SPARK] spark.etl.order_enrichment&lt;br&gt;
  └─ [AIRFLOW] airflow.dag.payment_sync&lt;/p&gt;

&lt;p&gt;⬇️  DOWNSTREAM (depends on this node):&lt;br&gt;
  └─ [DBT] dbt.production.revenue_monthly  (owner: &lt;a href="mailto:analytics@company.com"&gt;analytics@company.com&lt;/a&gt;)&lt;br&gt;
  └─ [SPARK] spark.ml.churn_features       (owner: &lt;a href="mailto:ml-team@company.com"&gt;ml-team@company.com&lt;/a&gt;)&lt;br&gt;
  └─ [DBT] dbt.production.executive_kpis   (owner: &lt;a href="mailto:data@company.com"&gt;data@company.com&lt;/a&gt;)&lt;br&gt;
  ... and 8 more&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now you can see the blast radius. The ML team's churn model feeds off `orders`. So does the executive KPI dashboard. One column rename, two very unhappy teams.

---

## Step 3: Run an Impact Assessment Before You Merge

This is the step that turns DataLineage from a debugging tool into a **prevention** tool.

Before any schema change, call `POST /lineage/impact` with the proposed change:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
def assess_schema_change_impact(&lt;br&gt;
    client: DataLineageClient,&lt;br&gt;
    node_id: str,&lt;br&gt;
    proposed_changes: list[dict]&lt;br&gt;
) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Simulate a schema change and identify every affected downstream consumer.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proposed_changes format:
    [{"type": "rename_column", "from": "old_name", "to": "new_name"}]
    [{"type": "drop_column",   "name": "column_name"}]
    [{"type": "change_type",   "column": "col", "from": "INT", "to": "STRING"}]
"""
payload = {
    "node_id": node_id,
    "changes": proposed_changes,
    "severity_threshold": "low"  # Catch even minor breakages
}

response = client._handle_response(
    requests.post(
        f"{client.base_url}/lineage/impact",
        json=payload,
        headers=client.headers
    )
)
return response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def format_impact_report(impact: dict) -&amp;gt; None:&lt;br&gt;
    """Print a CI-friendly impact report."""&lt;br&gt;
    affected = impact.get("affected_nodes", [])&lt;br&gt;
    severity_counts = {"high": 0, "medium": 0, "low": 0}&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print("\n🔍 IMPACT ASSESSMENT REPORT")
print("=" * 50)
print(f"Proposed change: {impact['change_summary']}")
print(f"Total affected nodes: {len(affected)}\n")

for node in affected:
    severity = node["impact_severity"]
    severity_counts[severity] += 1
    icon = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(severity, "⚪")

    print(f"{icon} [{severity.upper()}] {node['name']}")
    print(f"   Reason: {node['break_reason']}")
    print(f"   Owner:  {node['metadata'].get('owner', 'unknown')}\n")

print("SEVERITY SUMMARY:")
for level, count in severity_counts.items():
    print(f"  {level.capitalize()}: {count}")

# Exit non-zero if high-severity issues exist — useful in CI pipelines
if severity_counts["high"] &amp;gt; 0:
    print("\n❌ High-severity impacts detected. Review before merging.")
    return False

print("\n✅ No high-severity impacts. Proceed with caution.")
return True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Simulate renaming 'customer_id' to 'user_id' in orders
&lt;/h1&gt;

&lt;p&gt;impact = assess_schema_change_impact(&lt;br&gt;
    client,&lt;br&gt;
    node_id="dbt.production.orders",&lt;br&gt;
    proposed_changes=[&lt;br&gt;
        {"type": "rename_column", "from": "customer_id", "to": "user_id"}&lt;br&gt;
    ]&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;safe_to_merge = format_impact_report(impact)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Expected output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h1&gt;
  
  
  🔍 IMPACT ASSESSMENT REPORT
&lt;/h1&gt;

&lt;p&gt;Proposed change: Rename column 'customer_id' → 'user_id' in dbt.production.orders&lt;br&gt;
Total affected nodes: 7&lt;/p&gt;

&lt;p&gt;🔴 [HIGH] spark.ml.churn_features&lt;br&gt;
   Reason: Column 'customer_id' referenced in JOIN condition (line 34)&lt;br&gt;
   Owner:  &lt;a href="mailto:ml-team@company.com"&gt;ml-team@company.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔴 [HIGH] dbt.production.executive_kpis&lt;br&gt;
   Reason: Column 'customer_id' used in GROUP BY clause&lt;br&gt;
   Owner:  &lt;a href="mailto:data@company.com"&gt;data@company.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🟡 [MEDIUM] airflow.dag.weekly_report&lt;br&gt;
   Reason: Column referenced in downstream SELECT *&lt;br&gt;
   Owner:  &lt;a href="mailto:analytics@company.com"&gt;analytics@company.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SEVERITY SUMMARY:&lt;br&gt;
  High: 2&lt;br&gt;
  Medium: 1&lt;br&gt;
  Low: 4&lt;/p&gt;

&lt;p&gt;❌ High-severity impacts detected. Review before merging.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Putting It All Together: A Pre-Merge Check Script

Here's a complete script you can drop into your CI pipeline:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  !/usr/bin/env python3
&lt;/h1&gt;

&lt;p&gt;"""&lt;br&gt;
pre_merge_lineage_check.py&lt;/p&gt;

&lt;p&gt;Usage: python pre_merge_lineage_check.py --node dbt.production.orders \&lt;br&gt;
           --change rename_column --from customer_id --to user_id&lt;br&gt;
"""&lt;/p&gt;

&lt;p&gt;import argparse&lt;br&gt;
import sys&lt;/p&gt;

&lt;p&gt;def main():&lt;br&gt;
    parser = argparse.ArgumentParser(description="DataLineage pre-merge impact check")&lt;br&gt;
    parser.add_argument("--node", required=True)&lt;br&gt;
    parser.add_argument("--change", required=True, choices=["rename_column", "drop_column", "change_type"])&lt;br&gt;
    parser.add_argument("--from", dest="from_name", required=True)&lt;br&gt;
    parser.add_argument("--to", dest="to_name")&lt;br&gt;
    args = parser.parse_args()&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client = DataLineageClient()

change = {"type": args.change, "from": args.from_name}
if args.to_name:
    change["to"] = args.to_name

print(f"🔎 Assessing impact of {args.change} on {args.node}...")

impact = assess_schema_change_impact(client, args.node, [change])
safe = format_impact_report(impact)

sys.exit(0 if safe else 1)  # Non-zero exit blocks the merge in CI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    main()&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Add this to your GitHub Actions workflow and schema changes *cannot* merge without an impact review.

---

## The Bigger Picture

Manual dependency tracing is archaeology. You dig through layers of YAML, Spark configs, and Airflow DAGs hoping you've found everything — knowing you probably haven't.

DataLineage makes the invisible visible. Your pipeline has a graph structure whether you document it or not. This just makes it queryable.

The 2 AM Slack message? It becomes a PR comment: *"This rename affects 7 nodes. Here are the owners. Here's why it breaks."*

Ship with confidence. Your on-call engineer will thank you.

---

*Have a horror story about undocumented pipeline dependencies? Drop it in the comments — misery loves company.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>datalineage</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ComplianceWeave vs Vanta, Drata, Secureframe: Which Compliance Automation Tool Should You Use?</title>
      <dc:creator>Ahmed Moussa</dc:creator>
      <pubDate>Sat, 18 Jul 2026 06:45:00 +0000</pubDate>
      <link>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-7a7</link>
      <guid>https://dev.to/amoussa-eduhub/complianceweave-vs-vanta-drata-secureframe-which-compliance-automation-tool-should-you-use-7a7</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compliance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Automation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2024:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ComplianceWeave&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vs.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Field&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(An&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Engineer's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Honest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Take)"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devops&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;compliance&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tooling&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Compliance Automation in 2024: ComplianceWeave vs. The Field (An Engineer's Honest Take)&lt;/span&gt;

I want to start with a confession: I used to spend three weeks every year in what I privately called "evidence purgatory" — hunting down screenshots, exporting logs, and pestering teammates for policy documents. Compliance automation tools promised to end that. Some delivered. Some traded one kind of pain for another.

This post is my attempt to give you an honest map of the landscape, including where ComplianceWeave genuinely wins, where it doesn't, and how to decide which tool fits your situation.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Why This Space Is Harder Than It Looks&lt;/span&gt;

Compliance automation sounds simple: scan your infrastructure, check it against a framework, produce a report. The complexity hides in the edges. Which frameworks? Whose interpretation of a control? Can your security team &lt;span class="ge"&gt;*read*&lt;/span&gt; the output, or does it require a consultant to decode it? Can your &lt;span class="ge"&gt;*developers*&lt;/span&gt; actually integrate it into a workflow they already use?

Different tools have made different bets on these questions. Let's look at how they stack up.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Contenders&lt;/span&gt;

For this comparison, I'm evaluating &lt;span class="gs"&gt;**ComplianceWeave**&lt;/span&gt; alongside three representative categories of alternatives you'll encounter in the wild: &lt;span class="gs"&gt;**enterprise GRC platforms**&lt;/span&gt; (think legacy, GUI-heavy, consultant-friendly), &lt;span class="gs"&gt;**modern SaaS compliance tools**&lt;/span&gt; (slick dashboards, venture-backed, GUI-first), and &lt;span class="gs"&gt;**open-source DIY frameworks**&lt;/span&gt; (maximum control, maximum assembly required).
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Feature Comparison&lt;/span&gt;

| Feature | ComplianceWeave | Enterprise GRC | Modern SaaS | Open-Source DIY |
|---|---|---|---|---|
| SOC 2 support | ✅ | ✅ | ✅ | ⚠️ Partial |
| GDPR support | ✅ | ✅ | ⚠️ Partial | ⚠️ Partial |
| HIPAA support | ✅ | ✅ | ⚠️ Varies | ⚠️ Partial |
| ISO 27001 support | ✅ | ✅ | ⚠️ Add-on | ❌ Rare |
| Multi-framework single scan | ✅ | ❌ | ❌ | ❌ |
| API-first design | ✅ | ❌ | ❌ | ✅ |
| Self-hosted option | ✅ | ✅ | ❌ | ✅ |
| Python client | ✅ | ❌ | ❌ | Varies |
| Auto-generated audit reports | ✅ | ✅ | ✅ | ❌ |
| GUI dashboard | ⚠️ Basic | ✅ Excellent | ✅ Excellent | ❌ |
| Vendor ecosystem integrations | ⚠️ Growing | ✅ Extensive | ✅ Strong | ❌ |
| Pricing transparency | ✅ | ❌ | ⚠️ | ✅ |
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Breaking It Down&lt;/span&gt;

&lt;span class="gu"&gt;### ComplianceWeave&lt;/span&gt;

&lt;span class="gs"&gt;**Where it genuinely shines:**&lt;/span&gt;

The multi-framework single scan is the feature that made me stop and pay attention. Running separate scans for SOC 2 &lt;span class="ge"&gt;*and*&lt;/span&gt; ISO 27001 &lt;span class="ge"&gt;*and*&lt;/span&gt; HIPAA — and then reconciling overlapping controls across three different reports — is a time sink that most tools ignore entirely. ComplianceWeave treats overlapping controls as a first-class problem worth solving.

The API-first architecture is the other standout. If you've ever wanted to trigger a compliance check as part of a CI/CD pipeline, or pull findings into your own internal dashboard, or automate remediation workflows — you can actually do that here. The Python client is clean and reasonably documented, which matters more than it sounds. Most security tooling has Python bindings that feel like an afterthought.

The self-hosted option is significant for regulated industries. Healthcare organizations and financial services companies often cannot send infrastructure telemetry to a third-party SaaS. Having a self-hosted path isn't a checkbox — it's a blocker removed.

&lt;span class="gs"&gt;**Where alternatives are stronger:**&lt;/span&gt;

I won't pretend the GUI is a highlight. If your CISO or compliance officer lives in dashboards and needs to walk auditors through findings visually, ComplianceWeave's interface will feel spartan compared to the polished modern SaaS competitors. Those tools have invested heavily in making compliance &lt;span class="ge"&gt;*legible*&lt;/span&gt; to non-engineers, and it shows.

The vendor integration ecosystem is still maturing. Enterprise GRC platforms have spent years building connectors to every HR system, ticketing tool, and cloud provider under the sun. ComplianceWeave's integration library is growing but not yet at parity.

Community and third-party resources are thinner. If you get stuck, you're more likely to find a Stack Overflow answer or a detailed tutorial for the more established players.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Enterprise GRC Platforms&lt;/span&gt;

These tools were built for large compliance teams, not engineering teams. The audit trail features are often genuinely excellent — years of refinement based on actual auditor feedback. If your organization has a dedicated GRC team and a budget to match, the depth here is real.

The downsides are real too: implementation timelines measured in months, pricing that requires a procurement conversation, and developer experience that ranges from "cumbersome" to "actively hostile."
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Modern SaaS Compliance Tools&lt;/span&gt;

The best of these tools are genuinely impressive at what they do. Beautiful dashboards, strong integrations with AWS/GCP/Azure, and enough polish that you can hand the interface to a non-technical stakeholder without embarrassment.

The trade-offs: they're GUI-only (automation and scripting are second-class citizens), they're cloud-hosted with no self-hosted option, and multi-framework support often means purchasing separate add-ons. They're also optimized for SOC 2 specifically — HIPAA and ISO 27001 coverage can feel bolted on.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;### Open-Source DIY Frameworks&lt;/span&gt;

Maximum flexibility, zero licensing cost, and full control over your data. Also: you are the product team now. You'll spend real engineering hours wiring things together, writing your own report templates, and keeping up with framework updates. For a team with strong security engineering capacity and specific requirements that no commercial tool meets, this is a legitimate path. For most teams, the total cost of ownership is higher than it appears.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## Pricing Reality Check&lt;/span&gt;

Enterprise GRC: expect five-figure annual contracts, often with mandatory professional services.

Modern SaaS: typically $500–$2,000/month depending on scope, with per-framework or per-integration pricing adding up quickly.

ComplianceWeave: pricing is publicly available and usage-based, which makes budgeting predictable. Self-hosted reduces ongoing costs further.

Open-source: $0 in licensing, but budget for engineering time honestly.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## When to Use Each&lt;/span&gt;

&lt;span class="gs"&gt;**Choose ComplianceWeave if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Your team is engineering-led and wants compliance integrated into existing workflows
&lt;span class="p"&gt;-&lt;/span&gt; You need to demonstrate compliance across multiple frameworks simultaneously (common in B2B SaaS selling to enterprise and healthcare customers)
&lt;span class="p"&gt;-&lt;/span&gt; Data residency or regulatory requirements make SaaS-hosted tools a non-starter
&lt;span class="p"&gt;-&lt;/span&gt; You want to automate evidence collection via API rather than manage it manually

&lt;span class="gs"&gt;**Choose an enterprise GRC platform if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You have a large, dedicated compliance team with complex workflow and approval requirements
&lt;span class="p"&gt;-&lt;/span&gt; Your organization has existing procurement relationships and needs deep vendor integrations
&lt;span class="p"&gt;-&lt;/span&gt; Auditor familiarity with the platform is a meaningful advantage for you

&lt;span class="gs"&gt;**Choose a modern SaaS compliance tool if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; SOC 2 is your primary (or only) framework
&lt;span class="p"&gt;-&lt;/span&gt; Your compliance owner is non-technical and needs an excellent GUI experience
&lt;span class="p"&gt;-&lt;/span&gt; You're a smaller team that wants fast time-to-value and don't have self-hosting requirements

&lt;span class="gs"&gt;**Choose open-source DIY if:**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You have strong security engineering capacity in-house
&lt;span class="p"&gt;-&lt;/span&gt; Your requirements are genuinely unusual and no commercial tool fits
&lt;span class="p"&gt;-&lt;/span&gt; You're comfortable owning the maintenance burden long-term
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## The Honest Bottom Line&lt;/span&gt;

No tool in this space is a perfect fit for everyone. The compliance automation market has historically optimized for auditor satisfaction and enterprise sales cycles — which is why the developer experience across most tools is an afterthought.

ComplianceWeave's bet is that infrastructure teams shouldn't have to context-switch into a separate compliance universe. Whether that bet is right for your organization depends on who owns compliance at your company, what your regulatory surface looks like, and whether your team will actually use a tool that requires reading API documentation.

If the answer to that last question is "yes, enthusiastically" — ComplianceWeave is worth a serious look.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="ge"&gt;*Have experience with any of these tools? Corrections and counterpoints welcome in the comments.*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>python</category>
      <category>complianceautomation</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
