Cloud allgemein

Daten-Strategie für Cloud-Migrationen: Das Platform-Engineer-Playbook

Praktischer Guide zu Planung, Execution und Validierung deiner Daten-Strategie bei Cloud-Migrations — Schema-Evolution, Pipeline-Portabilität, Observability.

Harbinger Team3. April 20266 Min. LesezeitAktualisiert 14.5.2026
  • cloud-migration
  • data-strategy
  • platform-engineering
  • terraform
  • data-pipelines
Inhaltsverzeichnis14 Abschnitte

Daten-Strategie für Cloud-Migrationen: Das Platform-Engineer-Playbook

TL;DR

  • Cloud-Migrationen scheitern öfter am Daten-Layer als anderswo. Vier Phasen: Inventory → Dual-Write/Shadow → Cutover → Decommission.
  • Klassifizier Daten (Hot/Warm/Cold/Transient) vor Bewegung. Hot braucht Live-Replikation, Cold kann Off-Hours bulk-kopiert werden.
  • Niemals Hard-Cutover für Hot-Data — Dual-Write mit Reconciliation, dann Feature-Flag-Switch.
  • Audit-Trail, Rollback-Plan, 30 Tage Post-Cutover-Observability bevor Decommission.

Cloud-Migrations-Projekte scheitern öfter am Daten-Layer als anderswo. Networking, Compute und IAM kriegen thorough Attention — aber Daten werden oft als Nachher-Gedanke behandelt, in bulk die Nacht vor Cutover bewegt und gebetet. Dieser Guide existiert, um das Pattern zu ändern.

Ob du ein 50TB-Warehouse von On-Prem-Oracle zu BigQuery liftest, eine Kafka-Estate von Bare-Metal zu Amazon MSK re-platformst oder eine Fleet von Spark-ETL-Jobs zu Databricks auf Azure migrierst, die zugrundeliegenden Daten-Strategie-Fragen bleiben: Wann bewegst du was? Wie validierst du? Was ist dein Rollback?


Die vier Phasen einer Daten-Migration

Bevor du eine Zeile Terraform schreibst, mappe deine Migration auf vier diskrete Phasen. Phasen skippen ist, wie Projekte mit Phantom-Daten-Loss um 2 Uhr enden.

flowchart LR
    A[Inventory & Classification] --> B[Dual-Write & Shadow Mode]
    B --> C[Cutover & Validation]
    C --> D[Decommission & Observability]

Phase 1 — Inventory & Classification

Jedes Byte deiner Daten fällt in eine von vier Kategorien:

KlassifikationBeschreibungMigration-RiskBeispiel
HotAktiv read/written, latency-sensitiveHochOLTP-Tables, Event-Streams
WarmHäufig read, in Batch writtenMittelAggregated Reports, Feature-Stores
ColdArchived, selten readNiedrigCompliance-Archive, Raw-Event-Logs
TransientCache, Temp-Tables, in-flight StateN/A (rebuild)Redis-Caches, Kafka-Consumer-Offsets

Klassifizier vor Bewegung. Hot-Data braucht Live-Replikation. Cold kann off-Hours bulk-kopiert. Transient wird auf Target rebuilt.

Nutz Kombination aus Query-Logs, Column-Lineage-Tools und manuellen Interviews mit Daten-Consumern, um Inventory zu produzieren. Harbinger Explorer kann das beschleunigen — scannt Metadata across Multi-Cloud-Estates und surfact Dependency-Graphs automatisch.

Phase 2 — Dual-Write & Shadow Mode

Für Hot-Data niemals Hard-Cutover. Stattdessen Dual-Write-Phase: Writes landen simultan auf Source und Target, Reads laufen weiter von Source.

# Beispiel: Debezium-CDC-Connector für Dual-Write-Shadow-Replikation
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
  name: orders-cdc-shadow
  labels:
    strimzi.io/cluster: migration-connect
spec:
  class: io.debezium.connector.postgresql.PostgresConnector
  tasksMax: 4
  config:
    database.hostname: source-postgres.internal
    database.port: "5432"
    database.user: debezium_reader
    database.password: ${env:DEBEZIUM_PASSWORD}
    database.dbname: orders
    database.server.name: orders_shadow
    table.include.list: public.orders,public.order_items,public.customers
    slot.name: debezium_shadow_slot
    publication.autocreate.mode: filtered
    # Write zu Shadow-Topic für Target-Ingestion
    topic.prefix: shadow.migration
    transforms: Reroute
    transforms.Reroute.type: io.debezium.transforms.ByLogicalTableRouter
    transforms.Reroute.topic.regex: "shadow\.migration\.public\.(.*)"
    transforms.Reroute.topic.replacement: "target.ingest.$1"

Während Shadow-Mode laufen Reconciliation-Jobs auf Schedule (stündlich minimum) — vergleichen Row-Counts, Checksums und Sample-Records zwischen Source und Target.

Phase 3 — Cutover & Validation

Cutover ist kein Moment — ein Window. Explizit im Runbook definieren:

#!/bin/bash
# migration-cutover.sh — execute in tmux-Session mit Logging

set -euo pipefail
LOG_FILE="/var/log/migration/cutover-$(date +%Y%m%d-%H%M%S).log"

echo "=== CUTOVER START: $(date -u) ===" | tee -a $LOG_FILE

# 1. Write-Traffic zu Source drainen
echo "Step 1: Enabling write-drain flag in feature flag service..." | tee -a $LOG_FILE
curl -X PATCH https://flags.internal/v1/flags/db_write_drain   -H "Content-Type: application/json"   -d '{"enabled": true}' | tee -a $LOG_FILE

# 2. Warten auf in-flight Transactions
echo "Step 2: Waiting 30s for in-flight writes..." | tee -a $LOG_FILE
sleep 30

# 3. Finaler Reconciliation-Check
echo "Step 3: Running final reconciliation..." | tee -a $LOG_FILE
python3 /opt/migration/reconcile.py --source postgres://source-db --target bigquery://project/dataset --fail-on-diff

# 4. DNS / Connection-Strings switchen
echo "Step 4: Updating connection string secret in Vault..." | tee -a $LOG_FILE
vault kv put secret/db/orders   connection_string="postgresql://target-db.internal:5432/orders"   migrated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

# 5. Reads vom Target enablen
echo "Step 5: Flipping read flag..." | tee -a $LOG_FILE
curl -X PATCH https://flags.internal/v1/flags/db_read_source   -H "Content-Type: application/json"   -d '{"enabled": false}'

echo "=== CUTOVER COMPLETE: $(date -u) ===" | tee -a $LOG_FILE

Phase 4 — Decommission & Observability

Decommission Source nicht, bis du 30 Tage clean Production-Daten durch Target hast. Set Cross-System-Observability:

# Terraform: CloudWatch-Metric-Alarms für Post-Migration-Daten-Quality
resource "aws_cloudwatch_metric_alarm" "data_freshness" {
  alarm_name          = "migration-data-freshness-breach"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "MaxAgeMinutes"
  namespace           = "DataPlatform/Migration"
  period              = 300
  statistic           = "Maximum"
  threshold           = 15
  alarm_description   = "Data freshness degraded post-migration — possible pipeline stall"
  alarm_actions       = [aws_sns_topic.oncall.arn]

  dimensions = {
    Dataset = "orders"
    Stage   = "production"
  }
}

Schema-Evolution-Strategie

Schema-Changes during Migration sind ein Multiplying-Complexity-Factor. Jede Schema-Migration wird zu drei Problemen: Source-Schema, Migration-Mapping, Target-Schema.

Nutze ein Schema-Registry

Ob auf Avro, Protobuf oder JSON-Schema — laufe ein Schema-Registry auf beiden Seiten der Migration und enforce Backward-Compatibility:

# confluent-schema-registry config snippet
schema.compatibility.level: BACKWARD_TRANSITIVE

BACKWARD_TRANSITIVE bedeutet, jede neue Schema-Version kann von allen alten Consumern read werden — kritisch wenn Source und Target Consumer während Shadow-Mode koexistieren.

Column-Mapping-Patterns

Source-PatternTarget-PatternMigration-Tool
Camel-Case ColumnsSnake-Casedbt-rename-Macro
Implicit NullabilityExplicit NOT NULLSchema-Migration-Script
NUMERIC(18,4)DECIMAL(18,4)Type-Casting in Spark
Timestamp mit TZUTC-normalized TIMESTAMPSpark-from_utc_timestamp
Composite-PKSurrogate-Key + Composite-Indexdbt-Snapshot

Daten-Validation-Framework

Der Gold-Standard ist ein Three-Tier-Validation-Approach:

  1. Structural — Schema matches, keine missing Columns, Typen kompatibel
  2. Statistical — Row-Counts, Null-Rates, Value-Distributions in Tolerance
  3. Semantic — Business-Rules halten (z.B. Order-Total = Sum von Line-Items)
# Lightweight-Reconciliation mit PySpark (Great-Expectations-Alternative)
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, sum as spark_sum, abs as spark_abs

spark = SparkSession.builder.appName("MigrationReconcile").getOrCreate()

source_df = spark.read.format("jdbc").options(
    url="jdbc:postgresql://source-db:5432/orders",
    dbtable="public.orders",
    user="reader",
    password=dbutils.secrets.get("migration", "source-db-password")
).load()

target_df = spark.read.format("bigquery").option("table", "project.dataset.orders").load()

# Structural-Check
assert set(source_df.columns) == set(target_df.columns), "Column mismatch!"

# Statistical-Check
source_stats = source_df.agg(
    count("*").alias("row_count"),
    spark_sum("total_amount").alias("total_amount_sum")
).collect()[0]

target_stats = target_df.agg(
    count("*").alias("row_count"),
    spark_sum("total_amount").alias("total_amount_sum")
).collect()[0]

tolerance = 0.001  # 0.1% Toleranz
row_diff_pct = abs(source_stats["row_count"] - target_stats["row_count"]) / source_stats["row_count"]
sum_diff_pct = abs(source_stats["total_amount_sum"] - target_stats["total_amount_sum"]) / source_stats["total_amount_sum"]

assert row_diff_pct < tolerance, f"Row count divergence: {row_diff_pct:.4%}"
assert sum_diff_pct < tolerance, f"Sum divergence: {sum_diff_pct:.4%}"

print("Reconciliation passed")

Rollback-Planung

Jede Migrations-Phase braucht eine Rollback-Procedure dokumentiert vor Cutover-Beginn. Ein Rollback, der nicht in Staging rehearsed wurde, ist kein Rollback-Plan — ein Wunsch.

PhaseRollback-TriggerRollback-ActionRTO
Shadow-ModeReplication-Lag > 5 minCDC disablen, Connector fixen10 min
CutoverError-Rate > 1%Feature-Flags reverten2 min
Post-CutoverDaten-Quality-BreachSource re-enablen, Shadow re-open15 min

Observability-Stack für Migrations-Projekte

Post-Migration sollte deine Observability antworten: "Liefert die neue Platform Daten mit selber Quality und Freshness wie die alte?"

Instrumentier drei Signal-Typen:

  • Pipeline-Latency — p50/p95/p99 End-to-End-Job-Duration
  • Daten-Freshness — Max-Age des neuesten Records in Critical-Tables
  • Error-Rate — Failed Job-Runs als % der Total-Runs

Wenn du multiple migrated Workloads across Teams managst, wird Platform-Level-View essential. Tools wie Harbinger Explorer geben dir Unified-Operational-View across Cloud-Daten-Assets ohne Per-Team-Instrumentation-Overhead.


FAQ

Wie lange dauert eine typische Daten-Migration? Für 10-50TB Hot-Data mit Shadow-Mode: 3-6 Monate End-to-End. Cold-Data-Bulk-Copy mit klarer Tooling: 2-4 Wochen. Plan einen Monat Post-Cutover-Observability.

Welche Cloud-Region für DACH-Migrationen? eu-central-1 (Frankfurt) ist das pragmatische Default — DSGVO-konform, gute Latency. eu-west-1 (Dublin) für Cross-EU-Redundanz. eu-central-2 (Zürich) für CH-spezifische Compliance.

Kann ich CDC für Cold-Data nutzen? Overkill. Cold-Data: einmaliger Bulk-Copy mit pg_dump/COPY oder AWS-DMS-Full-Load. Spar CDC für Hot-Data.

Was kostet eine Cloud-Migration realistisch? Engineering-Aufwand: 1-3 Senior-Engineers für 3-6 Monate. Tools (Debezium-Hosting, DMS, etc.): 500-2.000 EUR/Monat. Cloud-Cost-Overlap während Shadow-Mode: ~30-50% Aufschlag auf Target-Cost.


Fazit

Eine Cloud-Migrations-Daten-Strategie ist kein One-Time-Document — eine lebende operative Praxis, die sich über Monate von careful, phased Execution spannt. Teams, die succeeden, behandeln Daten-Migration als Product-Delivery: Sie definieren Acceptance-Criteria, laufen Automated-Validation und planen für Failure.

Die Key-Takeaways:

  • Klassifizier Daten vor Bewegung
  • Nutze Dual-Write-Shadow-Mode für Hot-Data; niemals Hard-Cutover
  • Automatisier Reconciliation — manuelle Spot-Checks skalieren nicht
  • Definier Rollback-Procedures und rehearse sie
  • Bleib in Observability-Mode 30 Tage Post-Cutover bevor Decommission

Harbinger Explorer 7 Tage kostenlos testen — kriege Unified-Visibility across deine Cloud-Daten-Estate, track Migrations-Progress across Teams und fang Daten-Quality-Issues bevor sie Production erreichen.

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.