Anatomie einer KI-App-Plattform, die es bis in die Produktion schafft
Bitte ein Sprachmodell um eine React-App und du bekommst eine. Dieser Teil funktioniert, und das schon eine ganze Weile. Die Distanz zwischen dem und einem Produkt, in das sich deine Nutzer morgen einloggen — mit ihren Daten unversehrt nach deinem nächsten Deploy — überbrückt kein besseres Modell. Sie überbrückt eine Plattform: Isolation, Provisioning, Verifikation, Deployment und Recovery, jede so gebaut, dass der Agent falsch liegen darf und das System trotzdem konvergiert.
Dieser Beitrag ist die Landkarte. Jeder andere Beitrag in diesem Blog nimmt eine einzelne Box ins Detail.
Die Form der ganzen Maschine
Ein Projekt auf Adorable entsteht aus einer Chat-Nachricht und lebt als echte Infrastruktur:
Fünf Schichten, fünf verschiedene Fehlerdomänen:
- Eine Generierungs-Engine, die plant und den Code schreibt — und als fehlbar angenommen wird.
- Ein Verifikations-Gate, das entscheidet, was „fertig" bedeutet — und das ist kein LLM.
- Eine Laufzeitumgebung, die jedem Projekt harte Isolation gibt — ein Kubernetes-Namespace pro Projekt.
- Eine Datenbankschicht, gebaut für Tausende meist im Leerlauf befindlicher, vom Agenten erzeugter Datenbanken — Copy-on-Write-Branches, die auf null skalieren.
- Ein Deployment-Modell, in dem ein Release eine Metadaten-Operation mit verpflichtendem Rollback-Anker ist — eine Branch-Promotion, keine Kopie.
Der Rest dieses Beitrags geht die Schichten durch. Definitionen für jeden geprägten Begriff stehen im Glossar.
Schicht 1: die Generierungs-Engine plant, bevor sie tippt
Eine Anfrage für ein neues Projekt geht nie direkt in den Code. Eine System-Architekt-Stufe liest den vollständigen Service-Katalog, den aktuellen Zustand des Projekts und das Ergebnis der letzten Generierung und legt sich dann auf einen Plan fest: welche Services die App braucht (Datenbank, API-Server, Queue, CMS), wie sie integriert werden, und eine geordnete Menge von Aufgaben mit deklarierten Datei-Scopes und Abnahmekriterien.
Der Producer ist eine einzige flexible Tool-Calling-Schleife — er entscheidet selbst, wann er Kontext liest, Code schreibt, SQL ausführt und seine eigene Arbeit prüft, wobei für jeden aktiven Service funktionierende Integrationsbeispiele in seinen Kontext eingespeist werden. Zwei Disziplinen halten einen langen Build kohärent:
- Kontext-Kompression mit Fortschritts-Tracker. Verworfene History wird zusammengefasst statt verloren, und abgeschlossene Aktionen (geschriebene Dateien, ausgeführtes SQL) überleben das Trimmen — so wiederholt ein Build über 200 Schritte nicht Schritt 12.
- Anti-Spiral-Durchsetzung. Diagnose-Schleifen ohne Code-Änderungen werden zwangsweise unterbrochen; übergroße Einzeldatei-Ausgaben werden abgelehnt, bevor sie auf die Platte gelangen.
Die Architektur behandelt das Modell als austauschbares Bauteil: Planung, Coding und Analyse laufen auf separat konfigurierten Modellen, und keinem von ihnen wird die Arbeit der nächsten Schicht anvertraut.
Schicht 2: „fertig" entscheidet die Evidenz, nicht das Modell
Der Producer kann seine eigene Arbeit nicht als abgeschlossen markieren. Eine „Fertig"-Behauptung läuft durch die objektive Verifikation — Schichten, die Evidenz erzeugen, gegen die der Agent nicht argumentieren kann:
- der TypeScript-Compiler über jede deklarierte Datei, mit Import-Shape- und Modulgraph-Prüfungen;
- eine Contract-Probe: jede vom Architekten deklarierte API-Procedure muss am laufenden Pod ohne Serverfehler antworten, und jede deklarierte Tabelle muss existieren — eine Procedure, die der Agent zu schreiben vergaß, fällt objektiv durch, weil die Deklaration des Architekten der Vertrag ist, nicht die Erinnerung des Producers;
- die eigenen Unit-Tests der App, ausgeführt in ihrem Pod — jedes Scaffold kommt von Geburt an testbar, mit einem Test-Runner und einem funktionierenden
npm testab dem ersten Commit; - ein Headless-Browse der laufenden App, wenn sich Frontend-Dateien geändert haben.
Eine durchgefallene Schicht öffnet die Aufgabe wieder, mit der Fehler-Evidenz im Kontext. In dieser Kette gibt es bewusst keinen „LLM-Kritiker": ein Modell, das ein Modell benotet, konvergiert auf plausibel, nicht auf korrekt. Compiler, Probes und Tests verhandeln nicht.
Schicht 3: die Laufzeitumgebung ist ein Namespace pro Projekt
Jedes Projekt läuft in seinem eigenen Kubernetes-Namespace — mit eigenen Resource Quotas, Limit Ranges, Deployments, Services und Ingress, generiert aus einer deklarativen Spec. Der Blast Radius einer beliebigen App, auch einer fehlerhaften, ist ihr eigener Namespace. Subdomain-Routing pro App, Wildcard-TLS und Web-UIs pro Service fallen alle aus demselben Manifest-Generator heraus.
Ein Projekt ist auch nicht auf eine App beschränkt: es kann im selben Namespace um Geschwister-Apps und Katalog-Services wachsen, und die Plattform konvergiert an einem einzigen Engpass auf die deklarierte Menge — fail closed, niemals stillschweigend zurückfallen.
Idle-Ökonomie ist eine erstklassige Design-Randbedingung. Apps, die sich niemand ansieht, werden auf cgroup-Ebene eingefroren (null CPU, nahezu null Speicher, sofortiges Auftauen); ihre Datenbanken skalieren das Compute auf null. Eine Flotte von Wochenend-Projekten kostet, was sie soll: nichts, solange sie schläft.
Schicht 4: die Datenbankschicht wurde für Agenten gewählt, nicht für Menschen
Die Entität, die hier Datenbanken erzeugt, ist ein Agent, der Hunderte kurzlebiger, meist im Leerlauf befindlicher Datenbanken provisioniert — ein Workload, der die Annahmen von „Postgres pro App" sprengt. Die Antwort ist Postgres mit getrenntem Storage/Compute und Copy-on-Write-Branching (selbstgehostetes Neon):
- Ein Branch pro Projekt, in O(1) zur Generierungszeit erstellt.
- Scale-to-Zero-Compute, mit einem Rust-Proxy, der das Postgres-Wire-Protokoll spricht und die Datenbank mitten in der Verbindung aufweckt — Clients erfahren nie, dass sie geschlafen hat.
- Checkpoints und Point-in-Time-Forks als Primitive, was die nächsten beiden Ideen erst billig genug macht, um Defaults zu sein.
Billiges Branching ist auch das, was dem Agenten einen Undo-Button für Daten gibt: er macht einen Snapshot vor riskanten Migrationen und rollt zurück, wenn eine die Daten zerlegt — Code UND Daten zusammen, auf einen kohärenten Moment.
Schicht 5: ein Release ist eine Branch-Promotion mit Rollback-Anker
Der Gang in die Produktion bewegt keine Daten. Produktion ist eine dauerhafte Timeline; dev ist ein Copy-on-Write-Fork davon. Jedes Release pinnt einen git-Commit, archiviert den freigegebenen Baum, taggt einen Pre-Deploy-Checkpoint auf der Timeline von Prod und wendet ausstehende Migrationen an — eine Append-only-Ledger-Zeile pro Release. Re-Deploys behalten die Daten-Timeline der Produktion; die Prod-Daten durch die von dev zu ersetzen, ist eine separate, explizite, per Snapshot gesicherte Operation, niemals ein Seiteneffekt.
Der Rollback folgt derselben Disziplin: den gepinnten Commit erneut deployen, optional die Daten in die Ära dieses Releases zurückspielen — und die Plattform ist explizit darin, was ein Rollback physisch löschen darf: nur das, was aus git wiederherstellbar oder aus der Spec regenerierbar ist.
Das Bindegewebe: gebaut für Unterbrechung
Alles oben Genannte nimmt Fehler als normalen Input an. Builds sterben mitten im Flug (Pod-Evictions gibt es nun mal); ein Reconciliation-Sweep erkennt jeden unterbrochenen Lauf und stellt ein konsistentes, fortsetzbares Bild wieder her — Job-Zustand, Task-Kette, Locks, Chat-Flow. Secrets folgen einem einzigen verpflichtenden Pfad durch Vault in Namespace-Secrets, sodass ein Container-Neustart seine Credentials niemals verlieren kann. Resource-Tracking erfasst alles, was ein Projekt erzeugt, sodass das Löschen vollständig ist.
Nichts davon taucht in einer Demo auf. All das ist der Unterschied zwischen einer generierten Preview und Software, die du einem Kunden in die Hand geben kannst — und genau das ist das Argument des nächsten Beitrags.
FAQ
Was passiert, wenn die KI kaputten Code schreibt? Die Verifikation fängt es mit Evidenz ab — einem Compile-Fehler, einer durchgefallenen Contract-Probe, einem roten Test — und öffnet die Aufgabe mit dieser Evidenz im Kontext wieder. Der Agent korrigiert gegen Fakten, nicht gegen seine eigene Meinung über seine Arbeit.
Wo läuft meine App eigentlich? In ihrem eigenen Kubernetes-Namespace auf der Plattform: dedizierte Pods, Quotas, Ingress und TLS, mit eigenem PostgreSQL-Branch. Nicht in einer geteilten Sandbox.
Was kostet eine untätige App? Praktisch nichts. Container frieren ein (null CPU), das Datenbank-Compute skaliert auf null Replicas, und beide wachen beim nächsten Request transparent auf.
Sind Produktionsdaten von dev getrennt? Ja — vom ersten Deploy an hat die Produktion ihre eigene Daten-Timeline. Deploys wenden Migrationen darauf an; sie überschreiben sie nie mit dev-Daten. Die destruktive Richtung existiert nur als explizite, per Snapshot gesicherte Aktion.
Kann ich ein schlechtes Release zurückrollen? Jedes Release pinnt einen Commit und taggt einen Pre-Deploy-Checkpoint. Der Rollback stellt den Code, und optional die Daten, in die Ära dieses Releases zurück.
Kann ich meine App woanders hin mitnehmen?
Ein Projekt ist ein standardmäßiges git-Repository — Vite + React + tRPC + PostgreSQL, mit Migrationen unter db/migrations. Es synchronisiert mit GitHub und läuft überall, wo dieser Stack läuft.