Kann eine Migration ohne Ausfallzeit umkehrbar bleiben?
Planen Sie eine Migration ohne Ausfallzeit mit Strangler-Routing, dauerhaften Doppelschreibvorgängen, Abgleich und umkehrbarer Umschaltung.

Eine Migration ohne Ausfallzeit ist nur möglich, wenn das alte System gültig bleibt und Anfragen bedienen kann, bis das neue seine Übernahmefähigkeit bewiesen hat. Das klingt selbstverständlich, doch viele Migrationspläne zerstören diese Möglichkeit stillschweigend. Sie kopieren Daten, stellen einen Ersatz bereit, planen ein Wartungsfenster und nennen den Ausfall "Umschaltung". Der Ausfall ist kein Naturgesetz. Er entsteht, weil vier getrennte Aktionen gekoppelt werden: die Route ändern, den Schreiber wechseln, die Datenhoheit verlagern und den alten Pfad entfernen.
Ein sichereres Konzept trennt diese Aktionen und macht jede davon beobachtbar und umkehrbar. Anfragen laufen durch eine Routing-Nahtstelle. Schreibvorgänge tragen stabile Kennungen und lassen sich erneut abspielen. Eine Rückbefüllung hat eine definierte Position im Änderungsstrom. Der Abgleich vergleicht die fachliche Bedeutung, nicht die Form der Bytes. Die letzte Routenänderung wird damit zu einer kleinen Konfigurationsänderung statt zu einem Sprung über eine Lücke.
Das bedeutet nicht, dass Nutzer niemals einen Fehler sehen. Ein System kann verfügbar bleiben, während eine einzelne Anfrage aus denselben Gründen fehlschlägt wie vor der Migration. Das Versprechen ist enger und nützlicher: Die Migration selbst braucht keinen Zeitraum, in dem der Dienst jede Arbeit ablehnt, und der Betrieb kann den Verkehr zurückschicken, ohne die gestrige Datenbank rekonstruieren zu müssen.
Keine Ausfallzeit ist eine Eigenschaft des Routings
Die Anwendung bleibt verfügbar, wenn jede Anfrage während der gesamten Migration ein gültiges Ziel hat. Datenreplikation hilft, stellt allein aber keine Verfügbarkeit her. Wenn Clients direkt mit einem Server verbunden sind, den Sie ersetzen wollen, liegt die Routing-Entscheidung in Hunderten Clients und Sie kontrollieren die Umschaltung nicht.
Setzen Sie einen kontrollierten Entscheidungspunkt vor beide Implementierungen. Das kann ein API-Gateway, Reverse Proxy, eine Load-Balancer-Regel, die Zuordnung eines Nachrichten-Consumers oder ein Adapter im bestehenden Prozess sein. Die Technik ist weniger wichtig als der Vertrag: Der Betrieb muss das Ziel für einen kleinen Teil der Arbeit ändern können, ohne jeden Aufrufer neu bereitzustellen.
Wählen Sie diesen Teil an einer stabilen fachlichen Grenze. Routen Sie die Kontosuche getrennt von Kontoänderungen, den Rechnungsexport getrennt von der Rechnungserstellung oder einen Mandanten getrennt vom Rest. Schneiden Sie nicht danach, welche Controller-Datei sich am leichtesten ersetzen lässt. Eine Route, die Lese- und Schreibvorgänge, geplante Jobs und Callbacks mischt, liefert einen irreführend grünen Canary, während ein unbeobachteter Pfad weiter alte Daten verändert.
Ein minimaler Routeneintrag sollte so langweilig sein, dass man ihn während eines Vorfalls problemlos prüfen kann:
{
"capability": "invoice.read",
"cohort": "tenant-042",
"destination": "new",
"fallback": "old",
"revision": 17,
"changed_by": "change-1842"
}
capability benennt das Verhalten, nicht eine URL. cohort begrenzt die Exposition. fallback legt fest, wohin der Router eine Anfrage senden darf, wenn die neue Seite nicht gesund ist. Die Revision macht gleichzeitige Änderungen sichtbar, und die Änderungsreferenz sagt der Einsatzleitung, warum die Route verschoben wurde. Speichern Sie den Eintrag in einem System mit Änderungsverlauf und lassen Sie den Router die letzte gültige Konfiguration behalten, falls die Steuerungsebene ausfällt.
Gesundheitsprüfungen müssen die geroutete Fähigkeit testen. Ein Prozess, der /health beantwortet, kann trotzdem ohne Datenbankmigration, Entschlüsselungsschlüssel oder erreichbare Abhängigkeit laufen. Führen Sie einen kleinen Lesevorgang oder eine synthetische Operation aus, die dieselbe Kette wie echter Verkehr nutzt, mit eigens dafür reservierten Daten. Halten Sie automatisches Fallback bei Schreibvorgängen konservativ. Eine Leseanfrage auf der alten Seite zu wiederholen ist meist harmlos. Ein akzeptierter Schreibvorgang kann bei Wiederholung eine zweite Bestellung, Zahlung oder Akte erzeugen.
Die Strangler-Nahtstelle muss jeden Eingang erfassen
Strangler-Routing funktioniert nur, wenn die Nahtstelle alle Wege abfängt, über die eine Fähigkeit ins System gelangt. Martin Fowlers Beschreibung des Strangler-Fig-Musters betont den schrittweisen Ersatz um das alte System herum. Teams erinnern sich oft an "schrittweise" und vergessen "herum". Wenn ein Nachtjob, Desktop-Client, Dateiimport oder eine Nachrichtenwarteschlange die Nahtstelle umgeht, können zwei Implementierungen ohne gemeinsame Verkehrsregel aktiv werden.
Erfassen Sie die Eingänge anhand von Laufzeitbelegen, nicht anhand des Architekturdiagramms. Prüfen Sie Zugriffsprotokolle, Queue-Bindings, Scheduler-Definitionen, Firewall-Flüsse, Batch-Steuersprache, Aufrufer gespeicherter Prozeduren und ausgehende Callbacks, die später als eingehende Arbeit zurückkehren. Altsysteme stellen denselben Vorgang oft über einen HTTP-Endpunkt, eine Terminaltransaktion und eine nach Mitternacht importierte Datei bereit. Behandeln Sie diese als eine Fähigkeit mit mehreren Adaptern.
Die Nahtstelle sollte Identität und Kontext vor der Weiterleitung normalisieren. Beide Seiten brauchen dieselbe Anfrage-ID, denselben Akteur, Mandanten, Autorisierungsentscheid, dieselbe Frist und denselben Idempotenzschlüssel. Wenn jede Implementierung diese Felder selbst ableitet, macht der Abgleich die Geschäftslogik für Unterschiede verantwortlich, die am Rand entstanden. Bewahren Sie den ursprünglichen Anfragekörper für Prüfzwecke auf, soweit die Richtlinie das erlaubt, aber übergeben Sie beiden Pfaden eine versionierte kanonische Hülle.
Nutzen Sie prozentuales Routing bei zustandsbehafteter Arbeit nicht als erste Steuerung. Ein zufälliger Canary mit zehn Prozent kann den ersten Schritt eines Ablaufs an die neue Seite und den Folgeschritt an die alte senden. Bevorzugen Sie einen deterministischen Schlüssel wie Mandant, Konto, Fall oder Workflow-ID. Der Router sollte für diesen Schlüssel dieselbe Antwort liefern, bis der Betrieb die Kohortenregel ändert.
Authentifizierung ist ein weiterer Eingang. Wenn das alte System Sitzungen erzeugt, die das neue nicht prüfen kann, erzwingt die erste geroutete Anfrage eine neue Anmeldung. Prüfen Sie entweder die bestehende Sitzung an der Nahtstelle und übergeben Sie eine kurzlebige signierte Identitätsaussage, oder bringen Sie beiden Seiten während der Koexistenz ein gemeinsames Sitzungsformat bei. Migrieren Sie Passwort-Hashes nicht durch erzwungene Passwortänderungen, sofern das Unternehmen diese Störung nicht bewusst akzeptiert hat.
Machen Sie schließlich die Routenauswertung in jedem Trace und jeder Protokollzeile sichtbar. Erfassen Sie Regelrevision, gewähltes Ziel, Fallback-Entscheidung und Kohortenschlüssel. Wenn ein Nutzer meldet, dass die gestrige Rechnung von der heutigen abweicht, müssen Sie wissen, welche Implementierung jede Anfrage bedient hat. Ein Dashboard mit nur aggregierten Verkehrsanteilen beantwortet diese Frage nicht.
Doppelte Schreibvorgänge brauchen eine dauerhafte Absicht
Die sichere Form des doppelten Schreibens hält eine dauerhafte fachliche Absicht fest und lässt unabhängige Worker sie auf beide Datenmodelle anwenden. Die unsichere Form lässt den Anfrage-Thread Datenbank A und danach Datenbank B aufrufen und hofft, dass beide Aufrufe gelingen. Dabei bleibt eine unvermeidliche Lücke: Der erste Commit kann erfolgreich sein, während der zweite ausläuft, und der Aufrufer weiß nicht, ob eine Wiederholung die Arbeit dupliziert.
Lassen Sie die aktuelle Autorität die fachliche Änderung und ein Outbox-Ereignis in derselben lokalen Transaktion committen. Ein Relay veröffentlicht das Ereignis, und ein Consumer wendet eine idempotente Projektion auf den neuen Speicher an. In einer frühen Migrationsphase bleibt der alte Speicher maßgeblich, selbst wenn die neue Projektion einige Sekunden zurückliegt. Später, nach der Routenänderung, kann sich die Richtung umkehren, damit ein Rollback möglich bleibt.
Die Schreibhülle braucht genug Informationen, um Duplikate abzuweisen und Reihenfolgefehler zu erkennen:
{
"event_id": "01J7M6R2K8N4T3Q9V5X1",
"aggregate_type": "invoice",
"aggregate_id": "inv-90318",
"aggregate_version": 44,
"operation": "invoice.adjusted",
"occurred_at": "2026-08-14T10:42:31Z",
"payload": {"line_id": "ln-8", "amount_minor": 1250}
}
Der Consumer speichert event_id unter einer Eindeutigkeitsbedingung in einer Tabelle verarbeiteter Ereignisse. Er wendet Version 44 erst nach Version 43 an oder parkt das Ereignis, bis die fehlende Version eintrifft. Die Nutzlast verwendet fachliche Einheiten wie kleinste Währungseinheiten statt formatierter Zeichenketten. Eine erfolgreiche doppelte Zustellung gibt das frühere Ergebnis zurück und führt den Vorgang nicht erneut aus.
Microsofts Dokumentation zum Wiederholungsmuster benennt den wichtigen Punkt klar: Ein Dienst kann die Arbeit abschließen und die Antwort verlieren, sodass eine Wiederholung einen nicht idempotenten Vorgang erneut ausführt. Migrationsverkehr erzeugt diesen Zustand regelmäßig, weil Relays neu starten und sich Netzwerkpfade ändern. Ein Idempotenzschlüssel ist mehr als API-Komfort. Er belegt, dass zwei Zustellungen dieselbe Absicht darstellen.
Einige Schreibvorgänge lassen sich nicht sicher wiederholen, besonders Aufrufe an externe Stellen ohne Idempotenzunterstützung. Lassen Sie diese Nebenwirkung während der Koexistenz hinter der bestehenden Autorität. Replizieren Sie den daraus entstandenen Zustand, nicht den auslösenden Befehl. Dieselbe Zahlungsanweisung aus beiden Systemen zu senden ist kein doppeltes Schreiben, sondern löst zwei Zahlungen aus.
Beobachten Sie das Alter der Outbox, nicht nur die Anzahl ihrer Zeilen. Eine kleine Warteschlange mit einem seit sechs Stunden blockierten Ereignis kann schlimmer sein als eine große Warteschlange, die normal abläuft. Zeigen Sie das älteste unveröffentlichte Ereignis, das älteste nicht angewendete Ereignis je Aggregattyp, Wiederholungszahl, Dead-Letter-Grund und Versionslücke. Diese Signale zeigen, ob die Rollback-Daten wirklich aktuell sind.
Die Rückbefüllung muss den laufenden Änderungsstrom treffen
Eine Rückbefüllung ist erst vollständig, wenn ihr Snapshot an einer bekannten Position in den laufenden Änderungsstrom eingefügt wurde. Alle Zeilen bei weiterlaufender Produktion zu kopieren erzeugt ein bewegliches Ziel. Wenn der Kopierer ein Konto vor einer Aktualisierung liest, es aber schreibt, nachdem der Live-Consumer die Aktualisierung schon angewendet hat, kann der alte Snapshot neueren Zustand überschreiben.
Es gibt zwei solide Muster. Erstellen Sie einen konsistenten Snapshot, der an eine Log-Position gebunden ist, laden Sie ihn und wenden Sie dann Änderungen nach dieser Position an. Oder machen Sie jedes Backfill-Upsert von der Quellversion abhängig, sodass es keine neuere Projektion ersetzen kann. Produkte für Change Data Capture unterscheiden sich in der Syntax, aber die Invariante bleibt: Jeder kopierte Datensatz und jedes Live-Ereignis müssen eine vergleichbare Reihenfolge haben.
Die logische Replikation von PostgreSQL zeigt sowohl Nutzen als auch Grenzen. Laut Dokumentation folgen auf den ersten Tabellen-Snapshot die Änderungen innerhalb eines Abonnements in der Reihenfolge des Publishers. Dieselbe Dokumentation warnt, dass Schemadefinitionen und DDL in verbreiteten Versionen nicht repliziert werden und der Sequenzzustand vor einer Umschaltung lange separat behandelt werden musste. Das Handbuch Ihrer exakten Datenbankversion gehört in das Runbook. "Replikation aufgeholt" beweist nicht, dass ein Ziel neue Schreibvorgänge annehmen kann.
Drosseln Sie die Rückbefüllung anhand der Produktionslatenz statt mit einer festen Schätzung von Zeilen pro Sekunde. Lesen Sie nach Primärschlüsselbereichen, speichern Sie den abgeschlossenen Bereich und die Snapshot-Position und machen Sie jeden Block neu startbar. Große Transaktionen halten Logs zurück, verlängern Sperren und erschweren die Fortschrittskontrolle. Winzige Transaktionen verschwenden Overhead. Messen Sie die Wirkung auf die Quelle und wählen Sie eine Blockgröße, die sich innerhalb Ihrer Betriebsgrenzen bequem abschließen und wiederholen lässt.
Transformationen brauchen einen expliziten Fehlerspeicher. Wenn ein alter Status einen Wert enthält, den das neue Enum nicht akzeptiert, wandeln Sie ihn nicht stillschweigend in UNKNOWN um. Speichern Sie Quellschlüssel, Quellversion, Transformatorversion, Rohwert und Fehler. Der fachlich Verantwortliche kann dann entscheiden, ob der Wert einem bestehenden Zustand zugeordnet wird, einen neuen Zustand braucht oder alte Beschädigung offenlegt.
Befüllen Sie abgeleitete Summen nie zurück, ohne festzulegen, wer sie neu berechnet. Wenn das neue System den Rechnungssaldo aus Buchungen ableitet, während das alte eine veränderliche Saldo-Spalte speichert, vergleichen Sie Buchungen und fachlichen Endsaldo, kopieren die veränderliche Spalte aber nicht dauerhaft. Sonst überleben zwei Autoritäten im neuen Schema.
Der Abgleich vergleicht Invarianten, nicht Zeilen
Der Abgleich soll beweisen, dass beide Systeme dieselben fachlichen Aussagen treffen, auch wenn ihre Schemata verschieden sind. Zeilenzahlen und Prüfsummen finden fehlende Daten, taugen nach einem Architekturumbau aber nicht als wichtigste Abnahmeprüfung. Ein normalisiertes Postgres-Modell hat nicht dieselben Zeilen wie ein COBOL-Datensatzlayout, und ein TypeScript-Client serialisiert Felder nicht in derselben Reihenfolge wie ein Desktop-Programm.
Beginnen Sie mit Invarianten, auf die der Betrieb bereits vertraut: Jede gebuchte Position gehört zu einem Konto, Soll und Haben gleichen sich innerhalb einer Buchungsgrenze aus, die Rechnungssumme entspricht Positionen plus Steuer, ein geschlossener Fall hat ein Abschlussereignis und eine externe Referenz bleibt eindeutig. Schreiben Sie jede Invariante gegen beide Seiten und vergleichen Sie die Ergebnisse nach stabiler fachlicher ID.
Kanonisieren Sie bei Feldern, die übereinstimmen sollen, nur Unterschiede ohne fachliche Bedeutung. Normalisieren Sie Zeitstempel auf eine Präzision, Unicode auf eine vereinbarte Form, leere Zeichenketten und Nullwerte nach dem alten Verhalten und Geld auf ganzzahlige kleinste Einheiten. Schreiben Sie Kennungen nicht klein und runden Sie Zahlen nicht nur für einen grünen Bericht. Jede Normalisierungsregel kann einen Defekt verbergen, deshalb müssen Regeln versioniert und prüfbar bleiben.
Eine praktische Vergleichsabfrage gibt Abweichungen statt einer Erfolgszahl zurück:
SELECT account_id, old_balance_minor, new_balance_minor,
old_balance_minor - new_balance_minor AS delta_minor
FROM migration_account_balance
WHERE old_balance_minor <> new_balance_minor
ORDER BY ABS(old_balance_minor - new_balance_minor) DESC;
Die Ausgabeform zählt: Der Betrieb braucht die fachliche ID, beide Werte und die Differenz. Speichern Sie Lauf-ID des Abgleichs, Quell- und Zielposition, Abfrageversion, Start- und Endzeit, Zahl der Abweichungen und eine begrenzte Stichprobe. Ein Bericht ohne Positionen ist nicht reproduzierbar, weil sich beide Datenbanken darunter weiter verändern.
Ordnen Sie Abweichungen nach Ursache. Transportlücken bedeuten, dass ein Ereignis nie ankam. Reihenfolgelücken bedeuten, dass es zu früh oder zu spät kam. Transformationsfehler erzeugen aus der richtigen Quelle den falschen Zielzustand. Erwartete Unterschiede stammen aus bewussten Architekturänderungen wie dem Entfernen nachgestellter Leerzeichen. Unerklärte Unterschiede blockieren die Ausweitung der Kohorte, auch wenn ihre Zahl klein ist.
Fordern Sie kein universelles Null-Abweichungs-Ergebnis, wenn die Zeit selbst die Antwort ändert. Ein ablaufendes Angebot oder ein Live-Bestand kann zwischen aufeinanderfolgenden Lesevorgängen abweichen. Frieren Sie die maßgebliche Uhr ein, vergleichen Sie an passenden Log-Positionen oder prüfen Sie eine vom fachlich Verantwortlichen genehmigte Toleranz. Ein vom Migrationsteam gewähltes "nah genug" ist kein Abnahmekriterium.
Schattenlesevorgänge zeigen Verhalten vor dem Autoritätswechsel
Bei Schattenlesevorgängen verarbeitet die neue Implementierung echte Anfragen, während die alte Antwort weiterhin an den Aufrufer geht. Damit finden Sie semantische Fehler, die Datenprüfungen übersehen: Standardsortierung, Autorisierungsrandfälle, Rundung, lokale Formatierung, fehlende Datensätze und andere Fehlerbehandlung. Weil das neue Ergebnis verworfen wird, ist Shadowing nur bei Vorgängen ohne Nebenwirkungen sicher.
Klonen Sie die normalisierte Anfrage an der Nahtstelle und setzen Sie eine harte Frist, die kürzer als das Budget der Nutzeranfrage ist. Ein langsamer Schatten darf die maßgebliche Antwort nie verzögern. Entfernen oder ersetzen Sie Geheimnisse, die der neue Pfad nicht braucht, und markieren Sie die Anfrage, damit nachgelagerter Code keine E-Mail sendet, Caches verändert, Sitzungen verlängert oder abrechenbare Aufrufe auslöst.
Vergleichen Sie strukturierte Bedeutung statt roher Antwortbytes. Ignorieren Sie Trace-IDs und erzeugte Zeitstempel. Vergleichen Sie Statusklasse, geordnete oder ungeordnete Sammlungen laut Vertrag, Autorisierungsentscheidung, ausgewählte Felder, Fehlerkategorie und fachliche Summen. Speichern Sie ein geschwärztes Beispiel für jede neue Abweichungssignatur, nicht jede Antwort. Sonst wird der Vergleichsspeicher zu einer zweiten Kopie sensibler Produktionsdaten.
Schreibvorgänge als Schatten auszuführen und die Datenbanktransaktion zurückzurollen ist meist unsicher. Externe Aufrufe, Sequenzvergabe, Queue-Veröffentlichung und Trigger können die Transaktion verlassen. Prüfen Sie einen Schreibvorgang mit aufgezeichnetem Verkehr in einer isolierten Testumgebung oder führen Sie seine reine Entscheidungslogik gegen einen Snapshot aus und unterdrücken Sie den Commit-Adapter. Benennen Sie genau, was getestet wurde.
Leistungsvergleiche brauchen dieselbe Sorgfalt. Eine Schattenanfrage nach der alten Anfrage kann von einem warmen Cache profitieren, parallele Ausführung kann zusätzliche Last erzeugen, die kein System allein sieht. Messen Sie Latenz und Ressourcen beider Seiten, erklären Sie aber keinen Sieger, bevor der Test Cache-Zustand, Anfragemix und zusätzliche Schattenlast kontrolliert.
Das brauchbare Ausgangskriterium verbindet Abdeckung und sauberes Verhalten. Verfolgen Sie, welche Vorgänge, Autorisierungsrollen, Datenformen und Fehlerpfade der Schatten ausgeführt hat. Zehn Millionen Wiederholungen der üblichen Kontosuche beweisen nicht den seltenen Stornopfad. Routen Sie eine Kohorte erst, wenn ihr tatsächlicher Verhaltensumfang beobachtet oder bewusst getestet wurde.
Die Umschaltung ist eine Zustandsmaschine, kein Ereignis
Eine umkehrbare Umschaltung führt eine Fähigkeit durch benannte Zustände mit bewachten Übergängen. Ein Kalendereintrag kann einen Übergang genehmigen, aber die Uhr darf nicht entscheiden, ob er sicher ist. Der Betrieb sollte aktuelle Autorität, Route, Replikationsrichtung, Verzögerung und Rollback-Aktion auf einer Seite sehen.
Nutzen Sie Zustände, die Fakten statt Projektstimmung beschreiben:
old_only: Die alte Seite bedient und schreibt; die neue kann leer sein.old_authority: Beide Seiten erhalten aktuelle Daten; Nutzer erreichen weiterhin die alte Seite.new_canary: Eine deterministische Kohorte erreicht die neue Seite; alte Schreibvorgänge bleiben aktuell.new_primary: Der gesamte geeignete Verkehr erreicht die neue Seite; die alte bleibt für Rollback bereit.new_only: Das Rollback-Fenster ist geschlossen und alte Änderungspfade sind deaktiviert.
Jeder Übergang braucht maschinenlesbare Bedingungen. Der Wechsel zu new_canary kann null unerklärte Abgleichabweichungen, kein nicht angewendetes Ereignis über dem Verzögerungsbudget, erfolgreiche Schattenabdeckung aller wichtigen Vorgänge und eine getestete Routenumkehr verlangen. Für new_primary kommen Kapazitätsreserve, Besitz der Hintergrundjobs, Bereitschaft des Supports und die Bestätigung hinzu, dass Eingänge außerhalb von HTTP derselben Autorität folgen.
Halten Sie den Übergangsbefehl klein und idempotent. Er soll einen versionierten Routeneintrag aktualisieren und nicht Code bereitstellen, Schemaänderungen ausführen, Warteschlangen leeren und Worker neu starten. Wenn fünf Aktionen in einer bestimmten Minute geschehen müssen, kommt eine zu spät und das Rollback-Verfahren bleibt mehrdeutig.
Trennen Sie Stopp und Rollback. Ein Stopp friert die Kohortenerweiterung ein, während beide Seiten in ihren aktuellen Rollen weiterlaufen. Ein Rollback sendet Verkehr zur alten Seite, weil eine definierte Bedingung fehlgeschlagen ist. Eine Datenreparatur korrigiert den Zustand, nachdem der Betrieb den Fehler verstanden hat. Zielzeilen bei einem Alarm automatisch zur Quelle zurückzukopieren kann Beschädigung schneller verbreiten, als Menschen sie diagnostizieren.
Üben Sie den Rückwärtsübergang unter Produktionsbedingungen vor der breiten Umschaltung. Senden Sie eine Canary-Kohorte zur neuen Seite, erstellen und ändern Sie repräsentative Datensätze, bringen Sie die Kohorte zur alten Seite zurück und bestätigen Sie, dass diese Datensätze korrekt und erreichbar bleiben. Ein Rollback-Dokument, das nie echten Zustand bewegt hat, ist eine Theorie.
Rollback endet, wenn die alte Seite nichts Neues mehr lernt
Das alte System bleibt nur dann ein Rollback-Ziel, wenn es jede Zustandsänderung erhält, die es zur Wiederaufnahme der Autorität braucht. Eingeschaltete Server sind irrelevant, wenn die Datenbank nach dem ersten Schreibvorgang auf der neuen Seite zurückliegt. Definieren Sie das Rollback-Fenster anhand von Daten: Welche Vorgänge werden zurückrepliziert, welche Verzögerung ist akzeptabel und welche Änderungen kann das alte Modell nicht darstellen?
Rückwärtsreplikation wird schwierig, wenn die neue Architektur Zustände erlaubt, die das alte Schema nicht ausdrücken kann. Verschieben Sie diese Funktionen während der Koexistenz oder fügen Sie vor der Umschaltung eine kompatible Darstellung hinzu. Wenn das neue System etwa mehrere Anpassungen unterstützt, der alte Datensatz aber nur ein Betragsfeld hat, können Sie nach der zweiten Nutzeranpassung keinen Rollback versprechen, sofern der alte Pfad sie nicht bewahren kann.
Verwenden Sie eine Schemafolge aus Erweitern und Zusammenziehen. Fügen Sie Felder und Leser hinzu, die beide Formen tolerieren. Befüllen Sie die neue Form. Wechseln Sie die Schreiber. Beobachten Sie. Entfernen Sie die alte Form erst nach dem Rollback-Fenster. Zerstörerische Schemaänderungen, wiederverwendete Enum-Werte und verkürzte Felder löschen den Rückweg, auch wenn das Request-Routing noch umkehrbar aussieht.
Geplante Arbeit darf nur einen Besitzer haben. Eine Route kann interaktiven Verkehr an die neue Seite senden, während beide Scheduler Abrechnungen erzeugen oder Fälle schließen. Geben Sie jedem Job eine Lease oder ein Autoritätsflag, das vom selben Migrationszustand gesteuert wird, und erfassen Sie, welche Implementierung jeden Lauf übernommen hat. Übertragen Sie beim Rollback die Lease vor der Route, wenn der Job Daten ändern kann, die der alte Anfragepfad liest.
CodeHero behandelt diesen Koexistenzvertrag als Teil der Neuentwicklung: Das neue System in Go, Rust oder TypeScript wird mit einem Parity-Harness gegen aufgezeichneten Produktionsverkehr geprüft, und das Projekt wird in weniger als 30 Tagen geliefert. Dieses kurze Lieferversprechen ersetzt weder kundeneigene Abnahmebedingungen noch eine Rollback-Richtlinie. Es verhindert, dass diese Entscheidungen in einem langen Programm versteckt werden.
Legen Sie eine ausdrückliche Bedingung fest, die die Umkehrbarkeit beendet. Das kann die erste Nutzung eines nur neuen Zustands, das Löschen der Rückwärtsreplikation, eine zerstörerische Schemaänderung oder das Ende der betrieblichen Vereinbarung zur Unterstützung beider Seiten sein. Lassen Sie den verantwortlichen Eigentümer zustimmen. Wenn niemand diesen Punkt benennen kann, entdeckt das Team ihn während des Vorfalls, wenn Rollback bereits unmöglich ist.
Die letzte Routenänderung sollte ereignislos sein
Die letzte Umschaltung ist sicher, wenn sie nur die Standardroute einer Fähigkeit ändert, deren Kohorten bereits auf der neuen Seite liefen. Code, Daten, Jobs, Zugriffskontrollen, Dashboards, Bereitschaftsanweisungen und Rollback-Mechanik sind dann schon in Produktion. Das verbleibende Risiko ist die Größenordnung, deshalb verdienen Kapazität und Queue-Verhalten mehr Aufmerksamkeit als Funktionskorrektheit.
Erfassen Sie vor der Standardänderung einen Entscheidungsnachweis mit genauer Routenrevision, Replikationspositionen, Abgleichslauf, offenen Ausnahmen, Genehmiger und Rollback-Schwelle. Prüfen Sie, dass die alte Seite sofort die volle Last aufnehmen kann. Sie vor Ende des Rollback-Fensters zu verkleinern spart wenig und macht aus einer umkehrbaren Routenänderung eine Kapazitätswiederherstellung.
Ändern Sie die Route in Stufen, die zu Ihrer Fehlerdomäne passen. Ein Mandant kann mandantenspezifische Datenprobleme zeigen. Eine Region kann die Platzierung von Abhängigkeiten offenlegen. Ein Prozentanteil passt erst, wenn die Workflow-Affinität garantiert ist. Pausieren Sie zwischen Stufen lange genug, um den langsamsten relevanten Job oder Callback zu sehen, nicht für eine willkürliche Fünf-Minuten-Grafik.
Beobachten Sie Symptome, die Nutzer spüren: Fehlerkategorie, lange Latenzen, Queue-Alter, verletzte fachliche Invarianten, Autorisierungsablehnungen und Supportkontakte zur Kohorte. CPU und Speicher können ruhig aussehen, während Rechnungen aus der Suche verschwinden, weil ein Index-Consumer hängt. Verknüpfen Sie jede Rollback-Schwelle mit einem benannten Signal und einem Beobachtungsfenster.
Lassen Sie einen Operator den Übergangsbefehl verantworten und einen zweiten die Bedingungen lesen. Die zweite Person braucht die Befugnis, den Wechsel ohne Verhandlung im Vorfallkanal zu stoppen. Erfassen Sie beide Entscheidungen automatisch. Diese Trennung findet veraltete Dashboards, missverstandene Kohortenregeln und den bekannten Fehler, Schweigen als Zustimmung zu werten.
Wenn eine Schwelle auslöst, führen Sie die vorab getestete Routenumkehr aus und sichern Sie Belege. Improvisieren Sie keine Vorwärtskorrektur, während neue Fehler hinzukommen. Sobald der Verkehr auf der alten Seite stabil ist, frieren Sie bei Bedarf die betroffenen Zielschreibvorgänge ein, erfassen Positionen und analysieren. Umkehrbarkeit verschafft nur dann Zeit für sorgfältige Arbeit, wenn der Betrieb sie nutzt.
Entfernen Sie die Mechanik nach Ende des Rollback-Fensters bewusst. Deaktivieren Sie alte Schreiber, entziehen Sie Zugangsdaten, stoppen Sie Rückwärts-Consumer, archivieren Sie Abgleichbelege gemäß Richtlinie und bewahren Sie den Routenverlauf beim Änderungsnachweis auf. Ein vergessenes Dual-Write-Relay kann Monate später veraltete Daten wiederbeleben. Ein vergessenes Fallback kann eine kleine Anfrageklasse in eine Anwendung schicken, die niemand überwacht.
Die Migration ist gelungen, wenn das alte System nicht mehr gebraucht wird, nicht wenn die erste Anfrage das neue erreicht. Behandeln Sie bis dahin Routing-Zustand, Ereignisposition und Abgleichbelege wie Produktionsdaten. Fehlt eines davon, verlässt sich die Umschaltung auf Erinnerungen, und die sind am schwächsten, wenn der Pager am lautesten ist.
FAQ
Kann eine Migration wirklich ohne Ausfallzeit gelingen?
Ja, wenn jede Anfrage ein gültiges Ziel behält, während Route und Datenhoheit unabhängig wechseln. Die Aussage bedeutet keinen migrationsweiten Ausfall, nicht den garantierten Erfolg jeder einzelnen Anfrage.
Was bedeutet Strangler-Routing bei einer Legacy-Migration?
Strangler-Routing legt einen kontrollierten Entscheidungspunkt um alte und neue Implementierung und verschiebt Fähigkeiten oder Kohorten einzeln. Es scheitert, wenn Jobs, Queues, Desktop-Clients oder Callbacks diesen Punkt umgehen.
Sind doppelte Schreibvorgänge während einer Datenbankmigration sicher?
Zwei direkte Schreibvorgänge im Anfrage-Thread sind unsicher, weil einer committen kann, während der andere scheitert. Committen Sie fachliche Änderung und Outbox-Eintrag gemeinsam und wenden Sie danach ein idempotentes Ereignis auf den anderen Speicher an.
Wie werden Daten rückbefüllt, während Nutzer weiterschreiben?
Binden Sie den Snapshot an eine Position im Änderungsstrom und wenden Sie spätere Ereignisse in Reihenfolge an. Alternativ verhindert eine von der Quellversion abhängige Upsert-Bedingung, dass alte kopierte Daten ein neueres Ereignis überschreiben.
Was sollte ein Migrationsabgleich vergleichen?
Vergleichen Sie fachliche Invarianten und stabile Kennungen statt roher Zeilenlayouts. Erfassen Sie beide Werte, Differenz, Quell- und Zielpositionen, Abgleichsversion und genug Belege für jede unerklärte Abweichung.
Wann sind Schattenlesevorgänge sicher?
Sie sind bei Vorgängen ohne Nebenwirkungen sicher, wenn der Schatten eine eigene Frist hat und die Nutzerantwort nicht verzögert. Kennzeichnen Sie ihn so, dass nachgelagerter Code keine Nachrichten sendet, Sitzungen ändert, Ereignisse veröffentlicht oder Kosten auslöst.
Wie viel Verkehr sollte ein Migrations-Canary erhalten?
Beginnen Sie mit einer deterministischen Geschäftskohorte statt mit einem Zufallsanteil. Sie sollte klein genug für eine schnelle Umkehr sein, aber vollständige Abläufe, Rollen, Hintergrundjobs und Callbacks ausführen.
Was macht eine Umschaltung umkehrbar?
Die alte Seite muss aktuell, leistungsfähig und für die volle Last bereit bleiben. Dafür braucht es Rückwärtsdatenfluss, kompatible Schemata, eindeutigen Jobbesitz und eine mit echtem Zustand getestete Routenumkehr.
Wann sollte das Rollback-Fenster schließen?
Schließen Sie es an einer ausdrücklichen genehmigten Grenze, etwa beim ersten nur neuen Zustand oder einer zerstörerischen Schemaänderung. Lassen Sie es nicht enden, nur weil die neue Route einige Stunden ruhig war.
Was passiert nach der letzten Umschaltung?
Deaktivieren Sie alte Schreiber, entziehen Sie Zugangsdaten, stoppen Sie Rückwärts-Consumer, sichern Sie Routen- und Abgleichbelege und entfernen Sie Fallback-Regeln bewusst. Das alte Programm ist erst außer Betrieb, wenn kein unterstützter Pfad mehr dorthin schreibt oder Arbeit zurückleitet.