The databasePart 4 of 6

Wir geben dem Agenten einen Undo-Button für deine Daten

Ein KI-Agent, der deine App baut, fährt nebenbei auch Migrationen, Massen-Edits und Seeds — destruktive Operationen, die git nicht rückgängig machen kann, weil git nur Code versioniert. Also haben wir dem Agenten ein Daten-Undo gegeben, das er selbst bedient: Er macht vor einer riskanten Operation einen Snapshot und rollt zurück, falls die Operation die Daten kaputt macht. Wir zeigen, wie das auf Copy-on-Write-Postgres funktioniert, warum der Restore denselben Connection-String behält und warum eine ganze Flotte solcher Apps im Leerlauf nichts kostet.

Wir geben dem Agenten einen Undo-Button für deine Daten

Ein KI-Agent, der deine App baut, schreibt nicht nur Code — er fährt Migrationen, befüllt Tabellen und setzt Massen-UPDATEs ab. Code hat ein großartiges Undo: Es heißt git, und jede Generierung ist ein Commit. Daten haben das nicht. Ein Agent, der eine Migration fährt, die die falsche Spalte droppt, oder eine Massen-Neuberechnung der Preise mit einem Off-by-One im WHERE, hat etwas getan, an das git nicht herankommt. Für einen schnellen, autonomen Agenten sind die Daten die ungeschützte Fläche.

Wir haben dem Build-Agenten der Plattform bereits ein Commit-gebundenes Code-plus-Daten-Undo gegeben (Time-Travel für Code und Daten). In diesem Post geht es um die aktive Hälfte: Wir geben dem Agenten einen Snapshot/Restore, den er als Werkzeug bedient, damit er sich während eines Laufs selbst schützen kann — Snapshot vor einer riskanten Operation, Rollback, falls die Operation die Daten kaputt macht — und damit du in normaler Sprache darum bitten kannst, das Geschehene rückgängig zu machen. Der Kniff, der das überall bezahlbar macht, ist derselbe, der diese Apps gratis schlafen lässt.


Snapshots sind Marker, keine Kopien

Der naive Weg, eine destruktive Operation abzusichern, ist „kopier erstmal die Zeilen". Auf einer normalen Datenbank ist das echter Speicher und echte Zeit — absurd, das reflexhaft vor jedem riskanten Schritt zu tun, über Tausende kleiner Apps hinweg.

Adorable betreibt ein selbst gehostetes Neon: Storage (der Pageserver) ist von Compute (ein zustandsloses Postgres) getrennt, und die History ist eine Timeline — die Datenbank, rekonstruiert aus versionierten Pages + WAL bis zu einem LSN. Eine Timeline zu branchen ist Copy-on-Write und O(1), unabhängig von der Datenbankgröße. Ein Snapshot ist also keine Kopie deiner Daten; er ist ein Marker aus zwei Feldern — (timeline_id, lsn) —, der praktisch nichts kostet, bis du tatsächlich restorest.

Wenn ein Snapshot eine Zeile ist und keine Kopie, lässt sich der Default umdrehen: Snapshot vor jeder riskanten Operation, reflexhaft. Genau das tut der Agent jetzt.

Der Agent rahmt seine eigenen riskanten Operationen ein

Der Producer — der Agent, der deine App generiert und iteriert — ist derjenige, der die heiklen Operationen fährt. Also ist er auch derjenige, der die Snapshots macht. Zwei Wege:

  • Automatisch, an der klarsten Grenze. apply_migrations macht vor dem Lauf einen Sicherheits-Snapshot. Eine Migration, die eine Spalte droppt oder falsch backfillt, lässt sich nicht durch Code-Edits rückgängig machen — nur durch einen Daten-Restore —, also wird der Restore-Punkt festgehalten, ohne dass der Agent daran denken muss.
  • Bewusst, nach Ermessen. Ein snapshot_data-Tool lässt den Agenten vor allem anderen, das er als riskant einschätzt, einen Snapshot machen — einem Massen-Rewrite, einem großen Seed, einem datenverarbeitenden Schritt. Billig genug, dass „im Zweifel snapshotten" die richtige Gewohnheit ist.

Wenn ein späterer Schritt die Daten kaputt macht, ruft der Agent restore_data auf und rollt zurück — er erholt sich von einem Schaden, den er nicht per Code-Edit beheben kann. Das ist die Fähigkeit, die der Checkpoint zum Commit-Zeitpunkt nicht liefern kann: Er fängt Schaden ab, der mitten im Lauf, vor jedem Commit angerichtet wird. Der Agent kann die kühne Migration genau deshalb wagen, weil er sie zurücknehmen kann.

1 — snapshot_data()

2 — the risky migration / bulk write

3 — verify: data broke?

4 — restore_data() if broken

fork@lsn + repoint, in place

Producer

neon-conn-proxy

Postgres / one timeline

Ein Schutzmechanismus hält das Ganze sicher: Snapshot und Restore sind nicht symmetrisch. Ein Snapshot ist billig und nicht-destruktiv, also nimmt der Agent ihn bedenkenlos. Ein Restore setzt Daten zurück und startet das Compute neu, also nutzt der Agent ihn nur, um seinen eigenen Schaden innerhalb des Laufs rückgängig zu machen — deine historischen Daten zurückzudrehen ist eine Entscheidung, die du triffst, nicht der Agent für dich (mehr dazu unten).

Restore an Ort und Stelle: Der Connection-String wandert nicht

Damit das mitten im Lauf — und mitten im Gespräch — brauchbar ist, muss der Restore stabil sein. Würde er einen neuen Datenbank-Endpoint zurückgeben, hieße jeder Restore, die laufende App neu zu konfigurieren. Also passiert der Restore an Ort und Stelle: die Timeline beim LSN des Snapshots forken, dann das Compute der App auf den Fork umbiegen — gleicher Datenbankname, gleicher DATABASE_URL. Die App verbindet sich nicht neu an einen anderen Ort; die Daten unter ihr rollen zurück. Das nutzt den bereits existierenden Fork-at-LSN-plus-Proxy-eigenen-Repoint-Pfad der Plattform wieder — dasselbe Primitiv, auf dem Deploy und Rollback aufsetzen.

Ein Undo, um das du bitten kannst

Der Selbstschutz des Agenten kommt zuerst — das ist heute schon live. Dieselben Snapshots sind auch als deine gedacht, und das ist die Richtung von hier aus: Weil der Restore stabil und projektweit ist, taucht er dort auf, wo du ohnehin bist — im Gespräch. Sag „dieser Import hat alles zerschossen, roll es zurück", und der Chat-Agent schlägt den Restore vor („Ich kann deine Daten auf den 14:14-Snapshot zurückrollen — soll ich?") und du bestätigst; er biegt deine Datenbank niemals von allein um. Ein Panel im Dashboard listet die Restore-Punkte auf und ist der Ort, an dem diese Bestätigung passiert. Die disruptive Richtung bleibt immer hinter einem menschlichen Ja.

Und sie schläft gratis

Warum das in jede App gehört, nicht nur in die viel beschäftigten: Die Datenbank einer Adorable-App ist Scale-to-Zero. Im Leerlauf → das Compute skaliert auf null Replicas und kostet nichts; der nächste Request weckt es in Sekunden (siehe Scale-to-Zero-Postgres). Die Snapshots sind Marker, also bleibt eine App mit 200 davon und ohne Traffic immer noch ~gratis. Ein Hochzeits-RSVP-Tool, ein saisonaler Shop, ein internes Tool, das zweimal die Woche benutzt wird — jedes kann ein volles Snapshot/Undo tragen und im Leerlauf ~0 $ beitragen. Es ist die Eigenschaft, die KI-App-Flotten überhaupt erst tragfähig macht (app.build, QwikBuild, Atoms betreiben aus genau diesem Grund Tausende von Scale-to-Zero-Datenbanken); hier geben wir diesen Spielraum für ein Sicherheitsnetz aus, nicht nur für die Leerlauf-Ersparnis.

Ein Restore-Punkt für die ganze Anwendung

Der Restore rollt die Datenbank des gesamten Projekts zurück — und das ist die richtige Granularität, keine Einschränkung. Bei Adorable ist ein Projekt eine Anwendung, und ihre Apps sind Microservices, die sich bewusst eine Datenbank teilen und auf die Daten der jeweils anderen verweisen. Die Daten eines Services ohne die anderen zurückzurollen würde diese serviceübergreifenden Verweise brechen, also muss ein konsistentes Undo die ganze Anwendung auf einmal abdecken — aus demselben Grund, aus dem du niemals die Hälfte eines Systems point-in-time restoren würdest. Die feinere Granularität — unabhängiges Undo für jeden Endnutzer einer mandantenfähigen App, die du gebaut hast — ist eine eigene Form (ein Branch pro Mandant) und ist zurückgestellt.

Warum das wichtig ist

Daten-Undo verwandelt destruktive Automatisierung von einem Risiko in eine Fähigkeit. Der Agent kann die heikle Migration fahren, weil der Boden ein Restore mit einem Tool-Call zu einem Zustand ist, der tatsächlich existiert hat; und du kannst die Daten eines schlechten Tages rückgängig machen, indem du fragst. Git hat dem Code diese Eigenschaft vor langer Zeit gegeben. Die Datenbank brauchte nur dasselbe Primitiv — einen Branch bei einem LSN — und einen Agenten, der weiß, dass er danach greifen sollte, bevor er etwas tut, das er bereuen könnte.

Bau auf der Plattform, die diese Beiträge beschreiben.

Beschreib deine App in einfachem Deutsch — Adorable schreibt den Code, richtet die Datenbank ein und bringt sie live.

Kostenlos loslegen