Cloud allgemein

SLAs für Datenplattformen designen: Reliability Engineering für Daten

Praxis-Leitfaden für SLAs in Datenplattformen: SLI/SLO/SLA-Framework, Datenqualitäts-SLOs, Alerting, Error-Budgets und welche Org-Practices wirklich tragen.

Harbinger Team14. Mai 20269 Min. LesezeitAktualisiert 14.5.2026
  • sla
  • slo
  • datenqualität
  • reliability
  • platform-engineering
  • observability
  • dach
Inhaltsverzeichnis27 Abschnitte

SLAs für Datenplattformen designen: Reliability Engineering für Daten

Site Reliability Engineering (SRE) hat uns ein sauberes Framework für Web-Service-Zuverlässigkeit geliefert: SLIs, SLOs, SLAs — getragen von Error-Budgets und blameless Post-Mortems. Datenplattformen brauchen denselben Anspruch — aber die Konzepte lassen sich nicht 1:1 übertragen. Eine Data-Pipeline ist kein API-Endpoint. Ihre „Availability" ist nuancierter, ihre Fehler sind oft lautlos.

Dieser Leitfaden adaptiert Reliability Engineering für Datenplattformen und liefert ein konkretes Framework, das Platform-Engineers durchsetzen können.

TL;DR

  • Pipeline ≠ API. Klassische Uptime-SLAs fangen die typischen Datenfehler (Late Data, Silent Loss, Schema Drift, Duplikate) nicht ab. Du brauchst data-spezifische SLIs: Freshness, Completeness, Accuracy, Consistency, Timeliness, Availability.
  • SLO am Business-Impact ausrichten, nicht an der Infrastruktur. Erst fragen: wer konsumiert die Daten wofür?
  • Error-Budget ist dein Verhandlungsinstrument. Budget aufgebraucht → Feature-Freeze, alles geht in Reliability.
  • Burn-Rate-Alerts statt SLI-Spam. 14,4×-Burn paged, 3× warnt, 1× kommt im Standup.
  • Tiering nach Konsument: Platinum (≤5 min) für Exec-Dashboards, Bronze (≤24 h) für Archive — Investition proportional.

Warum Datenplattformen SLAs brauchen

Data Pipelines fallen auf Arten aus, die einzigartig gefährlich sind:

Failure-ModeWarum es gefährlich ist
Late DataDashboards zeigen veraltete Metriken; Entscheidungen auf Datenstand von gestern
Silent Data LossZeilen verschwinden ohne Fehler; kein Alert feuert
Schema DriftDownstream-Queries brechen; Reports zeigen Nulls
DuplikateAnalytics überzählt; Finanz-Reports sind falsch
Quality DegradationDaten korrumpieren schleichend; kein einzelnes Event diagnostizierbar

Klassische Infra-SLAs (Uptime %) decken das nicht ab. Du brauchst data-spezifische SLIs.

Das SLI/SLO/SLA-Framework für Daten

Definitionen

SLI (Service Level Indicator)
  ↓ gemessen über
SLO (Service Level Objective)
  ↓ Commitment-Basis für
SLA (Service Level Agreement)
  ↓ Bruch löst aus
Konsequenzen (Credits, Eskalationen, etc.)

Data-SLI-Taxonomie

SLI-KategorieBeispiel-MetrikMessmethode
FreshnessMax-Alter der jüngsten Zeile in Fact-TableNOW() - MAX(updated_at)
Completeness% der erwarteten Records empfangenRow-Count vs. Source-System
Accuracy% der Records, die Validierung bestehendbt-Test-Pass-Rate
ConsistencyVerletzungen referentieller IntegritätFK-Constraint-Checks
TimelinessPipeline-Completion-Zeit vs. SLA-FensterAirflow-Task-Dauer
Availability% der Zeit, in der Tabellen abfragbar sindProbe-Query-Success-Rate

SLOs definieren

SLOs gehören auf das Niveau des Business-Impacts, nicht der Infra. Denke rückwärts: wie nutzen Consumer deine Daten?

Beispiel-SLO-Tabelle

Tabelle / DatasetFreshness-SLOCompleteness-SLOAccuracy-SLOMessfenster
fact_geopolitical_events≤ 15 Min Lag≥ 99,5% der Source-Records≥ 99,9% ValidierungRolling 30 Tage
dim_countries≤ 24 Stunden100% (bounded Set)100%Rolling 30 Tage
agg_risk_scores_hourly≤ 90 Min Lag≥ 99% der Stunden befüllt≥ 98% im Erwartungs-RangeRolling 30 Tage
mart_executive_dashboard≤ 1 Stunde Lag≥ 99,9%≥ 99,9%Rolling 30 Tage

Error-Budgets

Ein Error-Budget ist die erlaubte Menge SLO-Verletzung:

Error Budget = 1 - SLO-Ziel

Für Freshness-SLO von 99,5% (über 30 Tage = 43.200 Minuten):
Error Budget = 0,5% × 43.200 = 216 Minuten erlaubter Lag-Verletzung pro Monat

Wenn das Error-Budget aufgebraucht ist:

  • Feature-Deployments einfrieren
  • Engineering geht voll auf Reliability
  • Post-Mortem zwingend, bevor wieder geliefert wird

Data-SLIs mit dbt und SQL umsetzen

Freshness-Check

-- models/monitoring/sli_freshness.sql
SELECT
    table_name,
    MAX(event_timestamp) AS latest_record,
    EXTRACT(EPOCH FROM (NOW() - MAX(event_timestamp))) / 60 AS lag_minutes,
    CASE
        WHEN EXTRACT(EPOCH FROM (NOW() - MAX(event_timestamp))) / 60 <= 15 THEN 'OK'
        WHEN EXTRACT(EPOCH FROM (NOW() - MAX(event_timestamp))) / 60 <= 30 THEN 'WARNING'
        ELSE 'BREACH'
    END AS slo_status
FROM (
    SELECT 'fact_geopolitical_events' AS table_name, event_timestamp
    FROM {{ ref('fact_geopolitical_events') }}
    UNION ALL
    SELECT 'agg_risk_scores_hourly', hour_timestamp
    FROM {{ ref('agg_risk_scores_hourly') }}
) t
GROUP BY table_name;

Completeness-Check

-- dbt-Test: Row-Counts zwischen Source und Target vergleichen
-- tests/assert_completeness.sql
{% set expected_minimum_rows = 100 %}

SELECT COUNT(*) AS missing_count
FROM (
    SELECT event_id FROM {{ source('raw', 'events') }}
    EXCEPT
    SELECT event_id FROM {{ ref('fact_geopolitical_events') }}
) missing
HAVING COUNT(*) > {{ expected_minimum_rows }};

dbt-Generic-Tests für Datenqualitäts-SLOs

# models/schema.yml
models:
  - name: fact_geopolitical_events
    description: "Kern-Fact-Tabelle für geopolitische Events"
    meta:
      slo_freshness_minutes: 15
      slo_completeness_pct: 99.5
      slo_owner: "platform-team@harbinger.com"

    columns:
      - name: event_id
        tests:
          - unique
          - not_null

      - name: country_code
        tests:
          - not_null
          - accepted_values:
              values: "{{ var('valid_country_codes') }}"

      - name: severity_score
        tests:
          - not_null
          - dbt_utils.accepted_range:
              min_value: 0.0
              max_value: 10.0

      - name: event_timestamp
        tests:
          - not_null
          - dbt_utils.recency:
              datepart: minute
              interval: 30  # Daten müssen innerhalb 30 Minuten vorliegen

Architektur: SLO-Monitoring-Pipeline

graph TD
    subgraph Datenplattform
        A[Airflow Pipelines] --> B[fact / dim / agg tables]
        C[dbt Jobs] --> B
    end

    subgraph SLO-Monitoring
        B --> D[SLI Probe Queries
alle 5 Min]
        D --> E[slo_measurements Tabelle
TimescaleDB]
        E --> F[SLO Calculator
Rolling 30-Tage-Fenster]
        F --> G[slo_status Tabelle
PostgreSQL]
    end

    subgraph Alerting
        G --> H{SLO Status Check}
        H -->|WARNING: Budget zu 50% verbraucht| I[Slack Alert]
        H -->|CRITICAL: Budget aufgebraucht| J[PagerDuty]
        H -->|BREACH| K[Incident Auto-Created
+ Freeze-Flag gesetzt]
    end

    subgraph Dashboards
        G --> L[Grafana SLO Dashboard]
        E --> L
    end

Den SLO-Calculator implementieren

# slo_calculator.py — läuft als Kubernetes-CronJob alle 5 Minuten

import psycopg2
from datetime import datetime, timedelta, timezone

SLO_CONFIG = {
    "fact_geopolitical_events": {
        "freshness_slo_minutes": 15,
        "completeness_slo_pct": 99.5,
        "window_days": 30,
    },
    "agg_risk_scores_hourly": {
        "freshness_slo_minutes": 90,
        "completeness_slo_pct": 99.0,
        "window_days": 30,
    },
}

def calculate_error_budget(table: str, slo_pct: float, conn) -> dict:
    # Aktuellen Error-Budget-Verbrauch für eine Tabelle berechnen
    window_start = datetime.now(timezone.utc) - timedelta(days=30)
    
    with conn.cursor() as cur:
        sql = (
            "SELECT COUNT(*) AS total_measurements, "
            "SUM(CASE WHEN slo_met THEN 1 ELSE 0 END) AS passing_measurements, "
            "ROUND(100.0 * SUM(CASE WHEN slo_met THEN 1 ELSE 0 END) / COUNT(*), 4) AS actual_slo_pct "
            "FROM slo_measurements "
            "WHERE table_name = %s AND measured_at >= %s"
        )
        cur.execute(sql, (table, window_start))
        
        row = cur.fetchone()
        total, passing, actual_pct = row
        
        allowed_failures = total * (1 - slo_pct / 100)
        actual_failures = total - passing
        budget_remaining_pct = max(0, (allowed_failures - actual_failures) / allowed_failures * 100)
        
        return {
            "table": table,
            "slo_target_pct": slo_pct,
            "actual_pct": float(actual_pct),
            "budget_remaining_pct": budget_remaining_pct,
            "status": "OK" if budget_remaining_pct > 50
                      else "WARNING" if budget_remaining_pct > 0
                      else "EXHAUSTED",
        }

Alerting-Strategie

Alert-Fatigue ist der Feind

Alerte nicht auf jede SLI-Abweichung — alerte auf die Error-Budget-Burn-Rate:

Burn-RateSeverityAktion
> 14,4× (Budget in 2 h weg)PAGESofortige Incident-Response
> 6× (Budget in 5 h weg)URGENTOn-Call binnen 30 Min wecken
> 3× (Budget in 10 h weg)WARNINGInnerhalb 1 Stunde checken
> 1× (auf Kurs Richtung Aufbrauch)INFOIm Daily-Standup reviewen
# Prometheus-Alert-Rules für Data-SLOs
groups:
  - name: data_platform_slo
    rules:
      - alert: DataFreshnessBreachImmediate
        expr: |
          (
            data_slo_error_budget_burn_rate{table="fact_geopolitical_events"} > 14.4
          )
        for: 2m
        labels:
          severity: critical
          team: platform
        annotations:
          summary: "Data-SLO-Error-Budget brennt schnell: {{ $labels.table }}"
          description: |
            Tabelle {{ $labels.table }} verbrennt Error-Budget mit Rate {{ $value }}×.
            Budget wird in {{ printf "%.1f" (1 / $value * 720) }} Minuten aufgebraucht sein.
            Runbook: https://wiki.harbinger.com/runbooks/data-slo-breach

Organisatorische Practices

SLO-Review-Rhythmus

RhythmusReview
TäglichSLO-Dashboard im Standup (5 Min)
WöchentlichError-Budget-Report: Budget verbraucht, Top-Incidents
MonatlichSLO-Targets reviewen: passen die Targets noch zum Business-Bedarf?
QuartalsweiseSLA-Verhandlung mit internen Stakeholdern

Der Data-Incident-Prozess

Wenn ein SLO-Breach passiert:

  1. Detection (automatischer Alert feuert)
  2. Triage (On-Call schätzt Impact: welche Consumer betroffen, Severity)
  3. Mitigation (Datenqualität wiederherstellen; Backfill, Reruns, Rollback)
  4. Communication (Data-Consumer via Status-Page-Update benachrichtigen)
  5. Post-Mortem (binnen 48 Stunden; Timeline + Root-Cause + Action-Items)
  6. Action-Items (im Sprint getrackt; Owner zugewiesen, Deadline gesetzt)

Post-Mortem-Template

## Incident: [Titel]
**Datum**: YYYY-MM-DD
**Dauer**: X Stunden Y Minuten
**SLO-Breach**: Freshness-SLO für `fact_geopolitical_events` (Lag > 15 min für 3,2 h)
**Impact**: Risk-Score-Dashboard zeigte veraltete Daten; 3 Analyst-Teams betroffen

### Timeline
- 14:32 — Airflow-DAG `event_enrichment` startet; Upstream-API rate-limited
- 14:45 — Lag überschreitet 15-Minuten-SLO-Schwelle; Alert feuert nicht (Bug in Alert-Config)
- 17:12 — On-Call sieht veraltetes Dashboard bei Routine-Check
- 17:18 — Incident erklärt; Pipeline-Rerun gestartet
- 17:41 — Datenfrische wiederhergestellt; SLO erfüllt

### Root-Cause
Upstream-News-API begann ab 14:30 wegen erhöhter Ingestion-Volumes rate-limiting.
Retry-Logic nutzte Exponential-Backoff, max Retries (3) wurden lautlos verbraucht.

### Beitragende Faktoren
- Alert-Fehlkonfig: `for: 30m` statt `for: 2m` beim Freshness-Alert
- Kein Dead-Letter-Monitoring für gescheiterte API-Calls

### Action-Items
| Action | Owner | Bis |
| --- | --- | --- |
| Alert-`for`-Dauer auf 2m fixen | @platform-team | 2026-05-20 |
| DLQ-Monitoring für API-Ingestion hinzufügen | @platform-team | 2026-05-25 |
| Adaptive Rate-Limit-Handling implementieren | @data-eng | 2026-06-01 |

SLA-Tiers für interne Consumer

Nicht jeder Data-Consumer hat dieselben Anforderungen. Tiers definieren:

TierFreshnessCompletenessConsumer
Platinum≤ 5 Min≥ 99,9%Exec-Dashboards, Realtime-Alerts
Gold≤ 30 Min≥ 99,5%Operative Dashboards, Analyst-Reports
Silver≤ 4 Stunden≥ 99%Ad-hoc-Analyse, Data-Science-Exploration
Bronze≤ 24 Stunden≥ 98%Historische Archive, Compliance-Reporting

Tiering erlaubt es, Reliability-Investition proportional zu allokieren — überproportional in Pipelines, die Platinum-Consumer versorgen.

FAQ

Wie unterscheiden sich SLAs für Datenplattformen von API-SLAs?

API-SLAs messen meist Uptime und Latenz. Daten-SLAs müssen zusätzlich Freshness, Completeness und Accuracy abdecken — Failure-Modes, die bei klassischen Diensten nicht existieren. Eine API kann „verfügbar" sein und trotzdem falsche Daten liefern.

Wo starte ich, wenn ich noch gar keine SLOs habe?

Bei der wichtigsten Konsumenten-Sicht. Suche dir das eine Dashboard (oder den einen Mart), an dem Entscheidungen hängen, und definiere für dessen Quelltabellen Freshness + Completeness. Erst messen, dann verhandeln, dann targets schärfen.

Wie hoch soll ein SLO-Target sein?

Niedriger ansetzen, als du intuitiv möchtest. 99,9% klingt gut, kostet aber operativ ein Vielfaches von 99%. Beginne bei 99% und ziehe nur dann nach oben, wenn der Business-Impact einer Verletzung das Budget rechtfertigt.

Was tun, wenn das Error-Budget aufgebraucht ist?

Feature-Freeze auf der betroffenen Pipeline, Engineering geht auf Reliability. Klingt hart, ist aber genau die Logik, die das Framework wirksam macht: ohne Konsequenz ist ein SLO eine Wandtapete.

Fazit

Datenplattform-SLAs verwandeln das schwammige „die Daten sind falsch" in messbare, einklagbare Commitments. Das SLI/SLO/Error-Budget-Framework gibt Platform-Teams die Sprache, ehrlich mit Stakeholdern über die Kosten von Zuverlässigkeit zu reden — und das Mandat, sie zu schützen.

Plattformen wie Harbinger Explorer hängen an genau dieser Disziplin: wenn Risk-Scores echte Entscheidungen treiben, ist „die Daten waren veraltet" keine akzeptable Antwort.

Stand: 14. Mai 2026. Anbieter und Tooling entwickeln sich — verifiziere kritische Annahmen bei deinem konkreten Stack.

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.