Cloud allgemein

Data Observability: Freshness, Volume, Schema und Lineage erklärt

Dashboard zeigt 0 € Umsatz seit 48h. Pipeline hat nicht failed, kein Alert. Eine WHERE-Klausel droppt still alle Zeilen. Wie die fünf Säulen der Data Observability das fangen.

Harbinger Team14. Mai 20265 Min. LesezeitAktualisiert 14.5.2026
  • data-observability
  • data-quality
  • freshness
  • schema-monitoring
  • data-lineage
  • monitoring
  • data-engineering
Inhaltsverzeichnis10 Abschnitte

Das Dashboard zeigt 0 € Umsatz für die letzten 48 Stunden. Die Pipeline hat nicht failed. Kein Alert. Eine WHERE-Klausel droppt still alle Zeilen wegen NULL-Wert upstream. Data Observability existiert, um genau das zu fangen.

Observability in Software heißt: Du kannst den inneren Zustand eines Systems aus externen Outputs verstehen. Auf Daten angewandt: Sind meine Daten vollständig? Frisch? Korrekt? Hat sich unerwartet etwas geändert?

TL;DR

  • Fünf Säulen: Freshness, Volume, Schema, Distribution, Lineage.
  • Data-Testing (dbt-Tests, GE) prüft Assertions, die du vorab definierst — Observability detektiert kontinuierlich Anomalien, die du nicht vorhergesehen hast.
  • Stack ohne Tool-Sprawl: dbt + Elementary deckt alle fünf Säulen ab.
  • Schwerster Teil: Disziplin, auf Alerts zu reagieren. Alerts ohne Action = Noise.

Die fünf Säulen

SäuleFrageBeispiel-Failure
FreshnessWurde Daten kürzlich aktualisiert?Pipeline lief, lud 0 Zeilen; stiller Delay
VolumeErwartete Datenmenge da?Tabelle verliert über Nacht 30 % Rows
SchemaHat sich die Struktur unerwartet geändert?Spalte umbenannt, Typ geändert
DistributionStatistisch normal?Null-Rate springt von 0,1 % auf 40 %
LineageWoher kommt es, was hängt dran?Upstream-Change bricht 12 Downstream-Models

Freshness Monitoring

Einfachste Säule, oft die wertvollste.

-- PostgreSQL: Freshness-Check als geplanter Query
SELECT
    CASE
        WHEN MAX(updated_at) < NOW() - INTERVAL '2 hours'
        THEN 'STALE' ELSE 'FRESH'
    END AS freshness_status,
    MAX(updated_at) AS last_update,
    NOW() - MAX(updated_at) AS data_age
FROM warehouse.orders;

In dbt:

sources:
  - name: raw
    schema: raw_data
    tables:
      - name: orders
        freshness:
          warn_after: { count: 1, period: hour }
          error_after: { count: 3, period: hour }
        loaded_at_field: updated_at

Anti-Pattern: Freshness nur an der Quelle prüfen. Eine Pipeline kann erfolgreich laufen und am Target leere Daten produzieren, wenn Filter/Join alles killt. Auch am Ziel prüfen.

Volume Monitoring

Detektiert unerwartete Drops oder Spikes. Ein plötzlicher Zero-Row-Load bedeutet fast nie "die Quelle hatte keine Daten" — meist ist etwas kaputt.

import sqlalchemy as sa

engine = sa.create_engine("postgresql://...")

def check_volume_anomaly(table: str, date: str, threshold: float = 0.3) -> dict:
    with engine.connect() as conn:
        result = conn.execute(sa.text(
            "WITH daily_counts AS ("
            "    SELECT DATE(loaded_at) AS load_date, COUNT(*) AS row_count"
            f"   FROM {table}"
            "    WHERE loaded_at >= NOW() - INTERVAL '8 days'"
            "    GROUP BY DATE(loaded_at)"
            "),"
            "baseline AS (SELECT AVG(row_count) AS avg_count FROM daily_counts WHERE load_date < :check_date),"
            "today AS (SELECT row_count AS today_count FROM daily_counts WHERE load_date = :check_date)"
            "SELECT today.today_count, baseline.avg_count,"
            "    ABS(today.today_count - baseline.avg_count) / NULLIF(baseline.avg_count, 0) AS deviation"
            "FROM today, baseline"
        ), {"check_date": date}).fetchone()
    return { "deviation_pct": round(float(result.deviation or 0) * 100, 1) }

Volume-Monitoring funktioniert als relativer Check (Abweichung vom Baseline), nicht als Absolut-Threshold. Black-Friday-Volumen ist 10× Dienstag. Fester Threshold feuert an jedem Peak.

Schema Monitoring

Schema-Changes sind ein stiller Killer. Spalte wird umbenannt, neue NOT-NULL-Constraint, Typ wechselt von VARCHAR auf INT. Keine Errors — nur korrumpierte Outputs downstream.

import json, sqlalchemy as sa

def snapshot_schema(engine, table: str) -> dict:
    with engine.connect() as conn:
        columns = conn.execute(sa.text(
            "SELECT column_name, data_type, is_nullable, character_maximum_length"
            " FROM information_schema.columns WHERE table_name = :table"
            " ORDER BY ordinal_position"
        ), {"table": table}).fetchall()
    return {row.column_name: dict(row._mapping) for row in columns}

def compare_schemas(old: dict, new: dict) -> list:
    changes = []
    for col in old:
        if col not in new:
            changes.append(f"DROPPED: '{col}'")
        elif old[col]["data_type"] != new[col]["data_type"]:
            changes.append(f"TYPE: '{col}' {old[col]['data_type']} → {new[col]['data_type']}")
    for col in new:
        if col not in old:
            changes.append(f"ADDED: '{col}'")
    return changes

Schema-Snapshots als Files oder Metadata-Table speichern. Vergleich auf jedem Pipeline-Run.

Distribution Monitoring

Tracked statistische Eigenschaften: Null-Raten, Distinct-Counts, Min/Max, Mean/Median — und alertet bei signifikanten Abweichungen.

SELECT
    'orders' AS table_name,
    'amount' AS column_name,
    NOW() AS profiled_at,
    COUNT(*) AS total_rows,
    COUNT(amount) AS non_null_count,
    ROUND(100.0 * (COUNT(*) - COUNT(amount)) / COUNT(*), 2) AS null_pct,
    MIN(amount) AS min_val,
    MAX(amount) AS max_val,
    AVG(amount) AS mean_val,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median_val,
    STDDEV(amount) AS stddev_val
FROM warehouse.orders
WHERE order_date = CURRENT_DATE;

Power liegt im Speichern der Profile über Zeit und Vergleich zur Baseline. Null-Rate-Sprung von 0,2 % auf 15 % ist starkes Signal, dass upstream was passiert ist.

Lineage Monitoring

Beantwortet: Woher? Was hängt dran?

raw.orders ────→ stg_orders ────→ fct_orders ────→ dim_revenue_daily
raw.customers ─→ stg_customers ──→ fct_orders ─────→ report_executive_kpis
                                                      ↑
                            dim_revenue_daily ────────┘

report_executive_kpis hängt an drei Upstream-Models — das fragilste Endpoint.

dbt generiert Lineage automatisch aus ref() und source() Calls. Für Non-dbt-Pipelines: OpenLineage, Marquez oder DataHub via Instrumentierung.

Tool-Landschaft

ToolFreshnessVolumeSchemaDistributionLineageSaaS
Monte CarloJaJaJaJaJaJa
Soda CloudJaJaJaJaTeilweiseJa
dbt + ElementaryJaJaJaJaJa (via dbt)Ja (Elementary)
Great ExpectationsTeilweiseJaTeilweiseJaSelf-host
OpenLineage/MarquezJaSelf-host
Re:dataJaJaJaTeilweiseTeilweiseSelf-host

Für die meisten Teams am Anfang: dbt mit Elementary deckt alle fünf Säulen ab. Für größere Multi-Engine-Stacks: Monte Carlo.

Minimal-Observability-Stack ohne Tool-Sprawl

  1. Freshnessdbt source freshness (kostet nichts)
  2. Volumedbt test row_count > 0 + Singular-Tests mit Deviation-Logik
  3. Schema → dbt Schema-Tests (not_null, accepted_values) + Snapshot-Skript
  4. Distribution → Elementary (OSS dbt-Paket)
  5. Lineagedbt docs generate

Kostet nichts, braucht keine zusätzliche Infrastruktur, deckt die häufigsten Failures.

FAQ

Lohnt sich Monte Carlo für Mittelstand-DACH? Selten unter 50 Data-Praktiker:innen. Über das reicht dbt + Elementary plus ein paar Custom Scripts.

Wie DSGVO-konform Schema-Snapshots speichern? Schema-Snapshots enthalten keine personenbezogenen Daten. Trotzdem EU-Region (eu-central-1, West Europe).

Reicht Pipeline-Alerts für Observability? Nein. Pipeline kann erfolgreich laufen und stale, schemaverletzte oder unverteilte Daten liefern.

Was ist das Hauptproblem in der Praxis? Alert-Fatigue. 50 Alerts/Tag = alle ignoriert. Wenig, hochsignal-Alerts mit klarem Owner.

Stand: 14. Mai 2026.

H

Geschrieben von

Harbinger Team

Cloud-, Data- und AI-Engineer in DACH. Schreibt seit 2018 über infrastruktur­kritische Tech-Entscheidungen — keine Marketing- Folien, sondern echte Trade-offs aus Production-Workloads.

Hat dir das geholfen?

Jede Woche ein neuer Artikel über DACH-Cloud, Data und AI — direkt in dein Postfach. Kein Spam, kein Marketing-Sprech.

Kein Spam. 1-Klick-Abmeldung. Datenschutz bei Loops.so.