Solange ein System klein ist, reicht ein kurzes Wartungsfenster für Schemaänderungen. Sobald Kunden rund um die Uhr darauf zugreifen, ist jede Minute Ausfall verlorener Umsatz und verlorenes Vertrauen. Die Lösung ist kein grösseres Wartungsfenster, sondern eine Migrationsstrategie, die Alt und Neu gleichzeitig leben lässt.
Das Grundproblem: Code und Schema ändern sich nicht gleichzeitig
Bei einem Deployment laufen für kurze Zeit alte und neue Version der Anwendung parallel. Ändert man das Schema in einem Schritt, passt es entweder nicht mehr zum alten Code oder noch nicht zum neuen. Beides führt zu Fehlern. Der Ausweg heisst Expand and Contract — erweitern, umziehen, aufräumen.
Expand and Contract in drei Phasen
- Expand: Neue Spalte oder Tabelle additiv anlegen, ohne Altes zu entfernen. Der alte Code funktioniert weiter.
- Migrate: Anwendung schreibt in Alt und Neu, danach werden Bestandsdaten im Hintergrund übertragen (Backfill).
- Contract: Erst wenn alles auf der neuen Struktur läuft, wird die alte Spalte entfernt.
Die Regel lautet: niemals in einem Schritt löschen und umbenennen. Jede zerstörende Änderung kommt zuletzt und separat.
Backfills gehören in den Hintergrund
Millionen bestehende Zeilen auf einmal zu aktualisieren sperrt Tabellen und bremst das laufende System aus. Backfills laufen deshalb in kleinen Batches, gedrosselt und wiederholbar. Wichtig ist Idempotenz: Ein abgebrochener Backfill muss ohne Schaden erneut starten können.
Feature-Flags trennen Deploy von Release
Die neue Lese- oder Schreiblogik wird hinter einem Schalter ausgeliefert und erst aktiviert, wenn die Daten vollständig migriert sind. Geht etwas schief, schaltet man zurück, ohne ein neues Deployment. So wird die riskanteste Phase — der Umschaltmoment — kontrollierbar und jederzeit umkehrbar.
Warum sich der Aufwand rechnet
Zero-Downtime-Migrationen sind mehr Arbeit als ein schneller ALTER TABLE mit Wartungsfenster. Aber sie machen Änderungen ungefährlich und damit häufig. Ein Team, das jede Migration ohne Ausfall ausrollen kann, deployt öfter, sammelt weniger technische Schulden an und muss Änderungen nicht mehr für seltene Nachtfenster aufsparen. Der eigentliche Gewinn ist nicht die vermiedene Downtime, sondern die gewonnene Geschwindigkeit.
Rückwärtskompatibilität als Denkweise
Zero-Downtime beginnt im Kopf: Jede Änderung wird so entworfen, dass die vorherige Version weiterlebt. Neue Felder sind optional, neue Endpunkte ergänzen alte, statt sie zu ersetzen. Diese Disziplin kostet anfangs Nachdenken, macht aber jedes Deployment ungefährlich. Ein Team, das rückwärtskompatibel denkt, kann jederzeit zurückrollen, weil die alte Version nie vollständig abgeschaltet wurde, bevor die neue sich bewährt hat.
Migrationen beobachten, nicht nur ausführen
Eine Migration ohne Monitoring ist ein Blindflug. Während Backfill und Umschaltung laufen, müssen Fehlerraten, Latenzen und Datenkonsistenz sichtbar sein. Nur so erkennt man früh, dass etwas nicht stimmt, und kann über den Feature-Flag zurückschalten, bevor Nutzer betroffen sind. Der Unterschied zwischen einer riskanten und einer beherrschten Migration liegt oft nicht im Code, sondern darin, ob man sieht, was gerade passiert.
Datenbanken ändern sich immer. Die Frage ist nur, ob sie es mit oder ohne Stillstand tun.