Die App, die mein Arbeitsleben leichter machen sollte und die ich nie benutzt habe
Ich wollte endlich vernünftig SQL schreiben können. Also baute ich meinen eigenen Language Server und dann gleich eine ganze Desktop-App drumherum. Über 1.000 Commits und 24 Releases später war sie fertig. Benutzt habe ich sie trotzdem nicht: Während ich mein Problem löste, hatte die KI meinen Workflow verändert. SQL schrieb ich kaum noch selbst. Einen Nutzer fand mein Tool am Ende doch noch: die KI, der es jetzt als MCP-Server kontrollierten Datenbankzugriff ermöglicht. Eine Geschichte über technische Verliebtheit, Vibe Coding und die unangenehme Frage, ob man das, was man gerade baut, überhaupt noch braucht.
Springen wir drei Jahre zurück. Ich durfte an einem neuen Projekt arbeiten, einem Data Warehouse. Daten werden von A nach B gezogen, aufbereitet, transformiert, normalisiert. You get it.
Mein Steckenpferd damals war TypeScript. Ich war ein TypeScript-Wizard, wie man früher so schön sagte: Je typisierter ein Projekt, desto besser, und je komplexer, desto mehr Spaß. Brauchte man das produktiv? Nein. War es schön? Oh boy, yes.
Der Einstieg ins Projekt war ernüchternd. Zu implementieren gab es kaum etwas. Stattdessen schrieb ich eine SQL-Abfrage nach der anderen, gegen legacy Systeme, die so schlecht designt waren, dass mir in den ersten Monaten die Haare ausgingen. Nach acht Jahren als Entwickler, etlichen Datenbanken und so ziemlich jedem ORM hielt ich mich für ziemlich fit in SQL. Da lag ich falsch.
Also habe ich mich ein paar Wochen zu Hause eingeschlossen und MySQL von Grund auf gelernt. Das ging so weit, dass ich anfing, an MySQL selbst zu zweifeln und später sollte ich recht behalten.
Anfreunden konnte ich mich mit SQL trotzdem nicht. Die Sprache gibt es seit über 50 Jahren, warum zum Teufel gibt es keine ordentliche IDE-Unterstützung? Ich wollte doch nur das Minimum: doppelte Spaltennamen erkennen, Tippfehler in Tabellennamen finden, eine Warnung bekommen, wenn ich zwei inkompatible Spaltentypen vergleiche. Stattdessen war jede einzelne Abfrage eine Qual, besonders wenn sie über tausend Zeilen ging. Wie viele Stunden ich mit Collation-Fehlern verbracht habe, die nicht einmal verraten, um welche Spalte es geht.
Obendrauf kam unser ORM Drizzle, das eine dünne Abstraktion darüberlegt und teilweise eigene Fehler einbaut.
Skill issue? Auf jeden Fall, teilweise. Aber irgendwann keimte eine Idee: Ich baue meinen eigenen Language Server. Und zwar nicht irgendeinen, sondern die Luxusausführung. Einen, der die Metadaten der Tabellen und Spalten aus der Datenbank liest. Der mich warnt, wenn ich ein DATE mit einem DATETIME vergleiche. Der mir die Herkunft jeder abgeleiteten Spalte zeigt: Woher kommt sie, wie wird sie verwendet, was ist das überhaupt? Mit einem Autocomplete, das die Spalten einer CTE in der WITH-Klausel kennt. Es war mein Traumprojekt.
Sieben Rewrites und ein Kind
Ende 2024 setzte ich mich hin und baute einen Prototyp, von Hand, was heute kaum noch vorstellbar ist. Er konnte einfache Queries parsen, Typen prüfen, die Semantik checken und brauchbare Fehlermeldungen ausgeben. War die UI schön? Keineswegs. War ich stolz? Und wie.
Dann lief es, wie es mit privaten Projekten immer läuft. Man stößt auf ein kleines Problem und denkt sich: Dann bau ich es halt nochmal neu, diesmal richtig. In sieben Monaten entstanden so zwei Repos mit zusammen rund 22.000 Zeilen von Hand geschriebenem TypeScript und unzähligen Neuanfängen. Dann kam mein Kind, und das Projekt ruhte.
Zurück aus der Elternzeit, rein ins Vibe Coding
Ende letzten Jahres hatte ich wieder Zeit. KI war gerade aus den Kinderschuhen raus, und ich dachte mir: Warum vibecode ich mein Projekt nicht einfach? Als Lernprojekt für KI, und mit der leisen Hoffnung, es endlich fertigzubekommen.
Anfangs bin ich jede Zeile durchgegangen. Ich habe die KI gezwungen, Code nach meinen Vorstellungen zu schreiben, und versucht, alles zu verstehen. Dann habe ich die KI weggelegt und alles von Hand neu geschrieben, den Code entwirrt und aufgeräumt. Und dann habe ich neue Features wieder von der KI anbauen lassen. Die hat prompt die dritte Implementierung derselben Logik in einen zufälligen Ordner gelegt. Duplizierte Logik überall, meine schöne Codebase war wieder verunstaltet.
Die Zahlen dazu: In dreieinhalb Monaten entstanden knapp 500 Commits und rund eine Viertelmillion Zeilen Code. Zum Vergleich, von Hand hatte ich in sieben Monaten 22.000 geschafft.
Ein Nebeneffekt, wenn man einen Typchecker für SQL baut: Man prüft die Datenbank gleich mit. Beim Testen stieß ich auf eine Query, bei der MySQL schlicht das falsche Ergebnis liefert. WHERE col IS NULL OR col = 1 auf einer UNION-Derived-Table verschluckt die NULL-Zeile, obwohl jede Bedingung allein korrekt filtert. Ich habe es gemeldet, und Oracle hat es bestätigt (Bug #119799). 30 Jahre MySQL, und trotzdem filtert die Datenbank falsch.
Parallel veränderte sich die Arbeit. Immer mehr Code wurde mit KI generiert, reviewt und deployt, bis zu dem Punkt, an dem man vor allem derjenige ist, der die Verantwortung trägt, wenn etwas schiefgeht. Die eigene Aufgabe besteht dann darin, die Ausfallrate mit gründlichen Reviews und Tests so gering wie möglich zu halten.
Ich baute fleißig weiter. Aus der VS-Code-Extension wurde eine Desktop-App, Rust und Tauri: schnell geladen, sparsam im Speicher. Der Language Server wurde zur Nebensache, ich baute ein ganzes Ökosystem drumherum. Man schreibt eine Query, und es öffnet sich eine Tabelle. Darin kann man gruppieren, aggregieren, filtern und Charts erstellen, mit wenigen Klicks, typsicher und schön aufbereitet. Dazu kamen Dashboards, Pivot-Tabellen, Excel-Export und Auto-Updates. Nach etlichen Nächten nach dem Muster „das Feature noch, und das wäre auch schön“ stand ich bei über 1.000 Commits und 24 Releases. Im Spätsommer sagte ich mir: Jetzt ist sie fertig.
Und dann habe ich sie einfach nicht benutzt.
Das Problem ist verschwunden, während ich es gelöst habe
Während ich an der App gebaut habe, hat sich unsere Arbeitswelt so drastisch verändert, dass es den Bedarf nicht mehr gibt. Queries schreibe ich nicht mehr selbst. Das meiste SQL generiert heute die KI. Ich prüfe, führe aus, schaue mir die Laufzeiten an und ordne das Ergebnis in den Business-Kontext ein. Selbst schreiben muss man nur noch in Optimierungsbereichen jenseits von Gut und Böse.
Ich war enttäuscht. All die Arbeit und all die Ideen sollten für die Katz gewesen sein?
Neuer Nutzer: die KI
Also habe ich mich mit dem heutigen Stand der Technik hingesetzt und überlegt, was ich damit noch anfangen kann. Die Idee: ein MCP-Server obendrauf. Meine KI soll die Datenbank lesen können, aber nicht jede Tabelle und nicht jede Spalte. Ich will konfigurieren können, was sie sehen darf. Und genau dafür hatte ich ja das passende Werkzeug: einen Language Server, der jede Query bis auf die einzelne Spalte versteht.
So entstand ein MCP-Server, der zum Beispiel Queries ablehnt, die aus der Kundentabelle den Namen abfragen. Das Prinzip ist Default-Deny: Die KI sieht nur Tabellen und Spalten, die ich explizit freigebe, und jede Query läuft vor der Ausführung durch den Language Server. Für ihn existiert eine versteckte Spalte schlicht nicht, deshalb hilft auch kein Umweg über eine CTE, einen Alias oder ein Subselect, und selbst ein SELECT * wird nur zu den freigegebenen Spalten aufgelöst. Das schützt in zwei Richtungen: gegen eine KI, die aus Übereifer oder per Prompt-Injection an Daten will, die sie nichts angehen, und gegen ganz normale KI-Fehler, weil eine Query, die nicht typcheckt, gar nicht erst bei der Datenbank ankommt. Wie nötig das ist, habe ich beim Red-Teaming meines eigenen Servers gemerkt: Über information_schema und die mysql-Systemtabellen hätte sich ein Agent das versteckte Schema auflisten und sogar Passwort-Hashes lesen können. Das Loch ist inzwischen gestopft, aber es hat mir gezeigt: Eine KI auf eine Datenbank loszulassen, ohne zu prüfen, was sie da eigentlich abfragt, ist wirklich nie eine gute Idee.
Das ist das einzige Feature der ganzen App, das ich heute produktiv nutze, und auch nur auf meiner Testdatenbank. Aber es zeigt etwas, das ich erst im Nachhinein verstanden habe: Die Oberfläche für Menschen ist überflüssig geworden, das Verständnis darunter nicht. Der Nutzer meines Tools hat gewechselt, vom Entwickler zur KI.
War alles umsonst?
Vergeudete Lebenszeit? Ein Teil davon sicher. Aber das Projekt war mein Einstieg ins produktive Arbeiten mit KI, und dabei habe ich drei Dinge gelernt, die ich vorher für falsch gehalten hätte.
1. Wartbar muss Code heute für die KI sein, nicht für mich. Mein größtes vermeintliches Problem war Clean Code. Ich wollte immer, dass mein Code abstrakt und flexibel genug ist. Am Ende war das nie ein Problem. Selbst wenn die KI mir einen Monolithen hingestellt hat, musste ich ihn nie von Hand anpassen. Sie hat die Datei einfach mit den neuen Anforderungen komplett neu generiert. Das händische Ändern von Code, auf das ich jahrelang optimiert habe, findet schlicht nicht mehr statt.
2. Die KI ist nicht gescheitert, ich bin am Formulieren gescheitert. Ich erinnere mich an keine Aufgabe, an der die KI wirklich gescheitert wäre. Das Schwierige war immer, das Problem selbst zu verstehen und so zu beschreiben, dass die KI es so umsetzt, wie ich es erwarte. Sonst wird aus einer kleinen UI-Änderung ein fünfstündiges Agent-Babysitting, bei dem man nur darauf wartet, dass sie wieder etwas komplett anderes macht als besprochen.
3. Bevor man etwas baut, muss man fragen, ob man es in einem Jahr noch braucht. Ich habe für ein Problem von 2023 eine Lösung im Stil von 2023 gebaut und sie 2026 fertiggestellt. Was ich gebraucht hätte, war nicht mehr Features, sondern regelmäßig ein ehrlicher Blick darauf, ob ich selbst das Ding noch öffne.
Hat sich der Aufwand gelohnt? Als Produkt nicht. Als das teuerste und lehrreichste KI-Training, das ich je hatte: ja.





