Eine (meistens) dreiteilige Reihe
von Pramod Sadalage und Kevin Hartman
Die Methodik, die in Evolutionary Database Design beschrieben und in Refactoring Databases: Evolutionary Database Design operationalisiert wird, ist seit zwanzig Jahren klar. Die sieben Praktiken, der Katalog von über 70 benannten Refactorings, die Übergangsmechanismen – all das dokumentiert, von Experten begutachtet, gelehrt.
Diese Methodik erreichte 2010 mit Continuous Delivery (Kapitel 12: Managing Data) CI/CD. Migrationen wurden zu erstklassigen Artefakten in der Deployment-Pipeline. Die Disziplin der Datenbankänderungen als Code erreichte die breitere CI/CD-Bewegung. Was CD nicht löste, war die Isolation pro Pipeline: Pipelines konnten Migrationen ausführen, aber sie benötigten immer noch eine Zieldatenbank, und dieses Ziel war gemeinsam. Praxis Nr. 4 – Jeder bekommt seine eigene Datenbankinstanz – ist in den meisten Teams aspirativ geblieben, da echte produktionsähnliche Datenbanken pro Entwickler Zeit, Geld und DBA-Zyklen kosten. Die kompensierende Schicht, die zur Behebung der Lücke entstand (Mock-Objekte, gemeinsame Staging-Umgebungen, In-Memory-Datenbank-Ersetzungen, DBA-Ticket-Warteschlangen), wurde standardmäßig zur grundlegenden Methodik, nicht per Design.
Im Jahr 2026 kommt das Copy-on-Write-Datenbank-Branching in Databricks Lakebase. Ein sekundenschnelles Branching einer Terabyte-großen Produktionsdatenbank ohne Speicherverbrauch bei der Erstellung ist nun eine O(1)-Operation. Die Einschränkung, die Praxis Nr. 4 aspirativ hielt, ist aufgehoben.
Diese Serie beschreibt, was sich ändert, wenn die Einschränkung aufgehoben wird: nicht die Methodik – die bleibt –, sondern die Praktiken, die zum ersten Mal entstehen, die Team-weite Governance, die automatisch wird, die Rollenentwicklung für den DBA und das neue Substrat, das Agenten mit ihren menschlichen Kollegen teilen.
Jen ist die Entwicklerfigur aus Evolutionary Database Design. In diesem Aufsatz implementierte sie ein Datenbank-Refactoring – die Aufteilung eines inventory_code Feldes in location_code, batch_number und serial_number – als routinemäßige User Story, die veranschaulicht, dass DBAs und Entwickler zusammenarbeiten können, Schemata in kleinen Schritten weiterentwickelt werden können und Migrationen die Änderungen sicher vorantreiben.
Die Serie setzt zwanzig Jahre später bei Jen an. Die Methodik, der sie folgt, ist dieselbe, der sie 2003 folgte. Neu ist das Substrat unter ihrem Workflow: Copy-on-Write-Datenbank-Branching, das die Praktiken, die sie gelesen hat, im Produktionsmaßstab operativ real macht. In den drei Teilen dieser Serie ist sie dieselbe Jen in drei Bereichen – ihr Tag (Teil 1), ihr neues Playbook (Teil 2) und ihr Team (Teil 3).
Um zu verstehen, wie das funktioniert, gehen wir den Weg durch, wie eine Entwicklerin namens Jen eine Aufgabe implementiert, die besagt, dass der Benutzer den Standort, die Charge und die Seriennummer eines Produkts im Inventar sehen, suchen und aktualisieren können sollte.
Das Folgende beschreibt die verschiedenen Schritte, die Jen unternehmen muss, um diese Aufgabe zu erfüllen. Dabei vergleichen wir, wie sich Jens Workflow ändert, wenn sie mit herkömmlichen Datenbanken arbeitet und Lakebase verwendet, das Datenbank-Branching zu minimalen Kosten ermöglicht.
Jen nimmt eine scheinbar unkomplizierte Aufgabe in Angriff. Das Produktteam möchte es den Benutzern ermöglichen, beim Hinzufügen eines Artikels den Standort, die Charge und die Seriennummer zu erfassen und diese später im Anwendungsfluss zu verwenden. Von außen betrachtet wirkt die Änderung klein: ein Feld zum Bildschirm hinzufügen, den Wert speichern, ihn im Inventarbildschirm für einen Artikel anzeigen und ihn vielleicht später in einer nachgelagerten Entscheidung verwenden.
Für Jen ist die Anwendungsänderung leicht vorstellbar. Sie weiß, wo sich das Formular befindet. Sie weiß, welcher Dienst die Anfrage bearbeitet. Sie sieht das Modellobjekt, das mehr Attribute benötigt. Aber in dem Moment, in dem sie die Änderung vollständig nachvollzieht, erkennt sie die eigentliche Abhängigkeit: Die Datenbank muss sich ebenfalls ändern.
Einige neue Spalten werden benötigt, vorhandene Daten in der Produktionsumgebung müssen erhalten bleiben und semantisch korrekt sein. Die Anwendung muss alte und neue Daten sicher verarbeiten, und sie muss Tests hinzufügen, um zu beweisen, dass die neuen Felder korrekt gespeichert, gelesen und angezeigt werden. Was wie ein einfaches Feature aussah, ist nun eine koordinierte Anwendungs- und Datenbankänderung mit der zusätzlichen Verantwortung, sicherzustellen, dass das vorhandene Produktionsschema und die Daten in das neue Schema migriert werden.
Jen erstellt einen Code-Branch für die Arbeit, die sie vorhat, und da sie eine gemeinsame Datenbank verwenden und der Rest des Teams dieselbe Datenbank für die Entwicklung nutzt, beginnt sie sofort, über all die Änderungen nachzudenken, die sie in der Datenbankschicht einführen wird und die andere Benutzer der gemeinsamen Datenbank beeinträchtigen könnten, und beginnt zu planen, wie sie diese für andere sicher machen kann. Kann sie die Anwendungsänderung lokal ausführen und ihre Unit- und Integrationstests durchführen? Jede Option hat Kosten. Sie kann warten. Sie kann das Team bitten, sich abzustimmen. Sie kann ihr eigenes lokales Postgres in Docker aufsetzen, es mit einem veralteten pg_dump von vor einer Woche füttern und hoffen, dass die Unterschiede keine Rolle spielen. Sie kann auf eine lokale Datenbank in einem Container oder auf eine In-Memory-Datenbank H2 oder SQLite zurückgreifen, die schnell läuft, aber den falschen Dialekt verwendet, sodass ihre Tests lokal fehlschlagen und unbekannte Fehler auf echtem Postgres auftreten. Kann sie überhaupt ihre Schema- und Datenmigrationsskripte testen? Diese Angst, andere zu stören, verlangsamt sie und erlaubt ihr gleichzeitig nicht, verschiedene Optionen für die Erstellung des Features zu experimentieren.
Da in einer gemeinsamen Datenbank ein Entwickler möglicherweise eine Änderung der Geschäftslogik testet, ein anderer eine Datenmigration debuggt und jemand anderes Testdaten erstellt hat, die Jen nicht versteht. Wenn Jen ihre Schemaänderung auf die gemeinsame Datenbank anwendet, kann sie die Arbeit eines anderen brechen. Wenn jemand anderes das Schema ändert, während sie testet, sind ihre Ergebnisse möglicherweise nicht mehr zuverlässig. Wenn sie Testdaten hinzufügt, kann dies die Annahmen eines anderen Entwicklers beeinträchtigen.
Jen kann warten, bis die gemeinsame Datenbank frei ist, was das Team vor Kollisionen schützt, aber es verwandelt ein kleines Feature in ein Planungsproblem und Produktivitätsverlust. Sie kann sich manuell mit den anderen Entwicklern abstimmen: „Benutzt du gerade die Entwicklungsumgebung?“ „Kann ich eine Migration durchführen?“ „Bitte setze die Daten für die nächste Stunde nicht zurück.“ Etwas wie ein Staffelstab in einem Staffellauf. Das funktioniert eine Weile, aber es skaliert nicht, besonders mit einem Remote- oder Multi-Zeitzonen-Team.
Jen denkt an eine weitere Option: die Verwendung einer lokalen In-Memory-Datenbank. Sie weiß, dass diese Konfiguration nicht mit dem Zustand der von den anderen Teammitgliedern verwendeten Datenbank übereinstimmt, was bedeutet, dass sie keine Zuversicht in ihre Lösung hat, da die Änderung lokal funktionieren und später fehlschlagen könnte, wenn sie auf die echten Daten und das Schema in höheren Umgebungen wie Staging und Produktion trifft.
Das eigentliche Problem, mit dem Jen konfrontiert ist, ist ein langsames Feedback. Sie kann die Änderung vornehmen, aber es dauert, bis sie herausfindet, ob die Änderung funktioniert. Schnelles und realistisches Feedback fehlt, und ohne dieses Feedback wird die Datenbankänderung zu etwas, mit dem das Team vorsichtig umgeht und sich schließlich für die erste Lösung entscheidet, die funktioniert, und nie experimentiert oder mehrere Lösungen ausprobiert, was zu suboptimalen Lösungen, reduzierter Produktivität und unzufriedenen Entwicklern führt.
Mit Lakebase hat Jen die Möglichkeit, eine Datenbank für ihren individuellen Gebrauch zu verzweigen, und diese Fähigkeit verändert ihre Arbeitsweise komplett.
Anstatt darauf zu warten, dass die gemeinsame Entwicklungsumgebung verfügbar wird, erstellt Jen einen Datenbank-Branch databricks postgres create-branch für ihr Feature oder verwendet eine VS Code / Cursor Extension. Dies ändert die Arbeitsweise sofort. Sie bittet das Team nicht mehr um ein ruhiges Zeitfenster. Sie verhandelt nicht mehr mit anderen Entwicklern darüber, wer welche Migration wann ausführen kann. Sie versucht nicht mehr, ihre halbfertige Änderung vor den halbfertigen Änderungen aller anderen zu schützen. Sie hat ihren eigenen isolierten Datenbankbereich, der aus derselben Art von Datenbankumgebung erstellt wurde, die die Anwendung schließlich in der Produktion verwenden wird.
Der Branch gibt Jen eine schnelle Kopie des Datenbankzustands, mit dem sie arbeiten kann. Sie hat jetzt dieselbe Postgres-Engine, dasselbe Schema, dieselben Governance-Richtlinien und dieselben produktionsähnlichen Daten, die sie sehen würde, wenn sie die Produktion direkt abfragen würde. Der einzige Unterschied: Dieser Branch kann geändert, verworfen oder neu erstellt werden, ohne andere Workloads zu beeinträchtigen. Sie testet nicht gegen eine vereinfachte lokale Datenbank, die sich von der Produktion unterscheidet. Sie arbeitet mit demselben Datenbanktyp, den das Team in der Produktion verwendet, mit denselben Schema-Regeln, Einschränkungen, Indizes, Referenzdaten und Migrationshistorien, die Datenbankänderungen in der realen Welt erfolgreich oder fehlerhaft machen. Diese Realitätsnähe ist wichtig, da viele Datenbankprobleme nicht in isolierten Unit-Tests auftreten. Sie treten auf, wenn eine neue Migration auf bestehende Strukturen, Daten, Annahmen und Anwendungsverhalten trifft.
Jetzt kann Jen die Datenbankänderung als Teil des Designs behandeln, nicht nur als Bereitstellungsschritt. Sie kann zuerst die offensichtliche Version ausprobieren: die neuen Spalten hinzufügen, eine Standardlogik zum Aufteilen der vorhandenen Spalte festlegen, ein Datenbankmigrationsskript erstellen, die Anwendung aktualisieren und die Tests ausführen. Dann kann sie bessere Fragen stellen. Sollte dieses Migrationsskript für Produktionsdatenvolumen funktionieren, sind die Datenqualitäten in der Produktion so, wie ihr Skript sie erwartet? Verbirgt ein Datenmigrationsskript fehlende Geschäftsinformationen? Sollte die Präferenz als einfache Spalten, eine Nachschlagetabelle oder eine separate item_information-Tabelle modelliert werden, da später wahrscheinlich mehr Informationen hinzukommen? Benötigt das Abfragemuster einen Index? Wird dieses Design die nachgelagerte Berichterstattung erleichtern oder erschweren? Im alten Workflow werden diese Fragen oft komprimiert, da die Änderung der Datenbank kostspielig ist.
Im verzweigten Workflow kann Jen diese erkunden, während das Feature noch gestaltet wird. Der DBA kann sich mit ihr zusammenschließen, um sie über Produktionsnuancen und Datenvolumen zu beraten und so wertvolle Einblicke in das Design der Lösung zu geben, anstatt nachträglich zu überprüfen.
Jen schreibt das Migrationsskript. Was auch immer ihr Team verwendet – Flyway, Liquibase, Alembic, Knex, Prisma – das Skript befindet sich im Code-Repository, neben den Anwendungsänderungen. Schema- und Datenmigration reisen mit dem Code.
(Dies ist das Split Column Refactoring – eines von ca. 70 Mustern, die in Refactoring Databases katalogisiert sind, dem Buch, das die sieben Praktiken operationalisierte.)
Sie wendet die Migration mit flyway migrate auf ihren Branch an. Das Tool läuft in weniger als einer Sekunde gegen realitätsnah geformte Daten. Sie aktualisiert ihren Repository-Code, um die drei neuen Spalten zu lesen und zu schreiben. Sie führt ihre Testsuite aus. Tests laufen gegen echte Postgres-Daten, keine Mocks, keine In-Memory-Ersetzungen.
Wenn sie einen sauberen Startpunkt wünscht, um einen anderen Ansatz zu versuchen, verwirft sie den Branch und erstellt einen neuen von der Produktion. Eine weitere Sekunde. Keine Cleanup-Tickets. Kein DBA beteiligt.
Dieselbe Jen. Dasselbe Refactoring. Was sich geändert hat, ist die Fähigkeit.
Die Fähigkeit zu experimentieren ist wichtig. Evolutionäres Design und Entwicklung bedeutet nicht nur, eine vordefinierte Checkliste schnell abzuarbeiten. Es geht auch darum, zu lernen, während die Arbeit konkreter wird. Jen stellt möglicherweise fest, dass das erste Schema-Design funktioniert, aber umständliche Anwendungslogik erzeugt. Sie stellt möglicherweise fest, dass das zweite Design sauberer ist, aber die Migration bestehender Datensätze komplizierter macht. Sie stellt möglicherweise fest, dass eine kleine Normalisierungsentscheidung jetzt zukünftige Änderungen erleichtern würde. Das erste von ihr geschriebene Migrationsskript, die SUBSTRING-Indizes sind um eins falsch. Das destruktive DROP COLUMN wurde ausgeführt, bevor sie überprüfen konnte, ob die neuen Spalten korrekt gefüllt wurden. Da sie ihren eigenen Branch hat, sind diese Entdeckungen kostengünstig. Sie kann eine Migration anwenden, die Anwendung ausführen, die Daten inspizieren, mit einer weiteren Migration vorwärts rollen oder zurücksetzen und einen anderen Pfad versuchen.
Der Branch ändert auch die emotionale Haltung der Arbeit. Jen muss nicht übermäßig vorsichtig sein, weil jemand anderes von der gemeinsamen Entwicklungsumgebung abhängig sein könnte. Sie muss nicht jedes Experiment dem Team ankündigen. Sie muss keine Testdaten sofort bereinigen, weil ein anderer Entwickler darüber stolpern könnte. Ihr Branch ist ein sicherer Ort für unfertiges Denken. Er kann temporäre Tabellen, fehlgeschlagene Migrationsversuche, umständliche Testdaten und halbfertige Designs enthalten, ohne Lärm für andere zu erzeugen.
Gleichzeitig bedeutet Isolation keine Entkopplung von den Teamstandards. Jen schreibt immer noch Migrationsskripte. Sie hält den Anwendungscode und die Datenbankänderung immer noch zusammen. Sie führt immer noch Tests durch. Sie erwartet immer noch, dass das endgültige Design überprüft wird. Der Unterschied ist, dass sie den unordentlichen Teil der Arbeit privat und schnell erledigen kann, bevor sie das Team bittet, über die polierte Version nachzudenken. Bis sie einen Pull Request öffnet, kann sich die Konversation darauf konzentrieren, ob das Design richtig ist, nicht darauf, ob sie einen sicheren Ort zum Testen hatte.
Dies ist die entscheidende Veränderung: Der Datenbank-Branch gibt Jen schnelles, realistisches, isoliertes Feedback, das sie auch von ihren Tech-Leads oder DBAs überprüfen lassen kann, indem sie ihren Datenbank-Branch zeigt. Schnell bedeutet, dass sie die Umgebung erstellen kann, wenn sie sie braucht, nicht wenn jemand sie für sie bereitstellt. Realistisch bedeutet, dass sie gegen dieselbe Art von Datenbankverhalten testet, die in der Produktion wichtig ist. Isoliert bedeutet, dass ihre Experimente niemanden sonst unterbrechen. Zusammen verwandeln diese drei Eigenschaften die Datenbankänderung von einem Engpass in einen normalen Teil der Feature-Entwicklung.
Jen kann jetzt die Anwendung und die Datenbank gemeinsam vorantreiben. Ihr Code-Branch und ihr Datenbank-Branch werden zu zwei Seiten derselben Aufgabe. Einer enthält die Anwendungsänderungen. Der andere gibt diesen Änderungen eine echte Datenbank, gegen die sie laufen können. Anstatt zu warten, zu koordinieren oder mit einem vereinfachten Setup zu simulieren, kann Jen entwerfen, testen, überarbeiten und lernen. Das Feature ist immer noch klein, aber jetzt ist die Datenbank nicht mehr das, was es langsam macht.
Jen committet sowohl den Anwendungscode als auch das Migrationsskript. Sie öffnet einen PR.
CI macht dasselbe, was Jen gerade getan hat, aber für das Team: Es erstellt seinen eigenen temporären Lakebase-Branch, wendet die Migration an, führt die Anwendungs-Testsuite aus, führt Datenbanktests gegen das migrierte Schema aus, validiert die Migration selbst (lässt sich sauber anwenden, idempotent, umkehrbar) und postet einen schema-diff Kommentar im PR, der genau zeigt, welche Datenbankobjekte sich geändert haben.
Der Reviewer kann nun sehen, was die Schemaänderung bewirkt, inline mit dem Code, der sie verwendet, und seine kontextuelle Wahrnehmung von abstrakt zu konkret ändern.

Screenshot der Branch Diff Summary-Ansicht der Lakebase SCM Extension
Im alten Workflow lautete die Frage bei der Datenbankprüfung: "Wird dies die Datenbank beschädigen?" – eine Prüfung durch einen DBA, der jede Änderung isoliert betrachten musste, da jede Änderung Produktionsfolgen hatte, wenn sie unkontrolliert blieb. Die Prüfungen waren synchron. Zeitpläne kollidierten. Der Kalender des DBA wurde zu einer Warteschlange und manchmal wurde der DBA aus "Time to Market"-Gründen übersprungen.
Im neuen Workflow lautet die Frage: "Ist dies das richtige Design?" Der DBA hat bereits die von der CI gepostete Schema-Differenz gesehen. Sie haben bereits gesehen, dass die Migration auf einem echten Datenzweig erfolgreich war. Jen kann auch den DBA für eine Diskussion hinzuziehen, um zu zeigen, was sie sich vorstellt und welche anderen Optionen sie ausprobiert hat. Der DBA kann nach eigenem Zeitplan prüfen, nicht nach Jens. Sie können die Prüfung viel früher im Lösungsentwicklungszyklus durchführen und die Lösung in Bezug auf Datenintegrität, Indexierungsstrategie, zukünftige Erweiterbarkeit oder langfristige Wartbarkeit verbessern, nicht auf die schützende Sperrung, die früher ihre gesamte Zeit in Anspruch nahm.
Das Team prüft Code und Datenbank gemeinsam. Ein PR. Eine Konversation. Gleiches Fenster.
Die Migration wurde bereits gegen einen echten Datenzweig getestet. Die Anwendung wurde bereits gegen das geänderte Schema ausgeführt. Die Schema-Migration wurde geprüft. Der CI-Build hat genau die gleichen Schritte ausgeführt und war eine Stunde lang grün.
Wenn Jen zusammenführt, wird die Migration auf die nächste Umgebung angewendet, die Zweige für die Datenbank und den Code für die CI-Umgebung und Jen werden bereinigt. Dadurch wird sichergestellt, dass die Datenbankänderung keine Überraschung mehr am Release-Abend ist.
Was Jen gerade getan hat, ist die fünfte Praxis aus dem Essay von 2003: kontinuierliche Integration von Datenbankänderungen.
Datenbankänderungen werden Teil der normalen Entwicklung. Branching reduziert Wartezeiten, Risiken und Koordinationsaufwand. Jens tägliche Schleife gibt ihr jetzt schnelles, isoliertes Feedback auf der Datenbankebene.
In Teil 2 – Jens neuer Spielplan, erklären wir,was angehoben wurde undwarum die kompensierende Schicht, um die Jen ihr ganzes Leben lang gearbeitet hat, herausgenommen werden kann: Copy-on-Write-Branching, die Architektur, die es ermöglicht, und die daraus resultierenden Methodikoptimierungen.
In Teil 3 – Jens Team im großen Maßstab, betrachten wir, wie Jens Geschichte aussieht, wenn sie eine von fünfzig Entwicklerinnen ist, oder vielleicht arbeitet sie an einem White-Label-Produkt, oder sie arbeitet an einem modularen Monolithen mit vielen Domänen darin – Governance bei der Erstellung von Zweigen, die Neuausrichtung des DBA, der Agent im Loop und die Plattformdesign-Arbeit, die sich öffnet, wenn der Kalender des DBA keine Ticketwarteschlange mehr ist.
Für Leser, die eine Tour durch die IDE-Tools wünschen, die Jen in diesem Beitrag verwendet hat, gibt es den Begleiter: Plugin-Walkthrough – die Lakebase SCM Extension für VS Code / Cursor, Ende zu Ende.
Schließlich wird bald ein Lakebase App Dev Kit für Agenten zur Verwendung, begleitet von einem E-Book für Menschen, veröffentlicht.
(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag
Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.