ORMs sind Mist. Welche Alternativen gibt es?
Jedes ORM verspricht dasselbe: Sie schreiben Objekte, das ORM schreibt SQL. Über die Datenbank müssen Sie nie wieder nachdenken. Genau da liegt das Problem. Über die Datenbank müssen Sie immer nachdenken. Das ORM macht es nur schwerer.
In 25 Jahren Softwareentwicklung habe ich jedes große ORM in mehreren Sprachen eingesetzt, von Versicherungsplattformen bis zu Echtzeit-Dashboards für IoT. Hibernate, Entity Framework, SQLAlchemy, Sequelize, TypeORM, Prisma. Das Muster ist immer gleich. Am Anfang ist alles elegant. Ein paar Monate später kämpft das Team mit dem ORM statt mit den fachlichen Problemen.
Der grundsätzliche Bruch
Die Ursünde der ORMs hat einen Namen: Object-Relational Impedance Mismatch. Objekte haben Identität, Kapselung, Vererbung und Polymorphie. Relationale Tabellen haben Zeilen, Spalten, Fremdschlüssel und Mengenoperationen. Diese beiden Modelle lassen sich nicht sauber aufeinander abbilden. Jedes ORM ist ein aufwendiger Versuch, so zu tun, als ginge es doch.
SQL beruht auf relationaler Algebra: Projektion, Selektion, Joins und Mengenoperationen. Seine Stärke kommt aus diesem mathematischen Fundament, nicht aus objektorientiertem Denken. Wer es in einen Objektgraphen presst, lässt das ORM ständig zwischen zwei unvereinbaren Weltbildern übersetzen. Lazy Loading, Eager Loading, N+1-Probleme, Kaskaden, Identity Maps: Das sind keine zufälligen Bugs. Sie folgen zwangsläufig aus dem Versuch, eine Lücke zu überbrücken, die man besser nicht überbrückt.
Lassen Sie SQL einfach SQL sein. Dann verschwinden ganze Kategorien von ORM-Komplexität.
Die Abstraktion, die zuverlässig leckt
ORMs sind das Lehrbuchbeispiel einer undichten Abstraktion. Für CRUD-Operationen funktionieren sie wunderbar, also genau dort, wo Sie mit fünf Zeilen SQL ausgekommen wären. Brauchen Sie einen komplexen Join, eine Window Function oder eine rekursive CTE, arbeitet das ORM gegen Sie. Ebenso bei jeder Abfrage, die auch auf großen Datenmengen schnell bleiben muss.
Am Ende schreiben Sie ORM-Pseudo-SQL. Es ist schwerer zu lesen als echtes SQL, schwerer zu optimieren und ohne Rückgriff auf rohe Abfragen kaum zu debuggen. Die Abstraktion sollte Zeit sparen und kostet jetzt Zeit. Dazu kommt die Mühe herauszufinden, was das ORM hinter Ihrem Rücken erzeugt.
Und es wird schlimmer. Die meisten ORMs belassen es nicht beim Mapping. Sie bringen ihre eigene Abfragesprache mit. Hibernate hat HQL und die Criteria API, Doctrine hat DQL, Entity Framework hat LINQ to Entities. Jede davon ist eine proprietäre DSL, die fast wie SQL aussieht, aber kein SQL ist. Statt einer gut entworfenen, überall einsetzbaren Abfragesprache lernt Ihr Team einen Herstellerdialekt. Der funktioniert nirgendwo sonst, hat schlechtere Werkzeuge und greift trotzdem auf rohes SQL zurück, sobald es ernst wird.
Das sind die eigentlichen Kosten: nicht bloß eine weitere Abstraktionsschicht, sondern eine ganz neue Sprache. Sie will gelernt, gedebuggt und gepflegt werden. Und sie existiert nur, damit man die Sprache nicht sprechen muss, die Ihre Datenbank längst fließend beherrscht.
Das Problem reicht tiefer. Wer mit einem ORM groß wird, lernt SQL oft nie richtig. Modelle definieren und .findMany() aufrufen: kein Problem. Legen Sie denselben Leuten aber einen Ausführungsplan hin, erstarren sie. Das ORM hat mit der Datenbank auch das Wissen wegabstrahiert, das man braucht, um sie gut zu nutzen.
Die Erkenntnisfalle
Jede Abstraktionsschicht ist eine Wette: Es kostet weniger, das Darunterliegende nicht zu verstehen, als sich direkt damit zu befassen. Bei UI-Frameworks geht diese Wette meist auf. Bei Datenbanken geht sie öfter schief, als die ORM-Hersteller zugeben. Dabei entscheidet gerade die Datenbank, ob Ihre Anwendung in 20 Millisekunden antwortet oder in 20 Sekunden.
Ihre Datenbank zu kennen ist keine optionale Komplexität. Es ist Grundwissen. Ein ORM, das dieses Wissen versteckt, macht Ihr System nicht einfacher. Es verschiebt nur den Moment, in dem die Komplexität auftaucht. Und es sorgt dafür, dass Sie dann schlechter gerüstet sind.
Welche Alternativen gibt es?
Rohes SQL mit Typsicherheit
Mit Werkzeugen wie sqlc (Go) oder PgTyped (TypeScript) schreiben Sie reines SQL und erzeugen daraus typsicheren Code. Sie behalten die volle Kontrolle über Ihre Abfragen. Der Query Planner der Datenbank sieht genau das, was Sie geschrieben haben. Und Ihre IDE meldet Typfehler trotzdem schon beim Kompilieren.
Zu diesem Ansatz greife ich am häufigsten. SQL ist bereits eine deklarative, gut entworfene Sprache. Eine weitere Abstraktionsschicht darüber macht sie selten besser. Für Go zeigt Darbit den Ablauf mit sqlc Schritt für Schritt.
Query Builder
Kysely (TypeScript), Knex (JavaScript) und jOOQ (Java) liegen dazwischen. Sie bauen Abfragen kombinierbar zusammen, ohne so zu tun, als wäre Ihre Datenbank ein Objektgraph. Sie denken weiter in Tabellen, Joins und Bedingungen. Kysely und jOOQ spannen dazu das Sicherheitsnetz Ihres Typsystems.
Ihre Stärke zeigen Query Builder bei dynamischen Abfragen: Filter, Paginierung, bedingte Joins. Rohes SQL wird dort mit String-Verkettung schnell unhandlich. Query Builder lassen sich sauber kombinieren und verbergen dabei nicht, was sie erzeugen.
Dünne Mapping-Schichten
Wer kein ORM will, muss nicht gleich ganz auf rohes SQL setzen. Bibliotheken wie Drizzle ORM setzen auf SQL first: Die API folgt der Semantik von SQL, statt ein eigenes Objektmodell zu erfinden. Sie definieren zwar Schemas, aber Ihre Abfragen lesen sich wie SQL. Rohe Abfragen sind jederzeit ohne Reibung möglich.
Der entscheidende Unterschied: Dünne Mapper helfen Ihnen, SQL zu schreiben. Klassische ORMs versuchen, SQL zu ersetzen. Das eine skaliert. Das andere bricht.
KI verändert die Rechnung
Deshalb ist die Diskussion gerade jetzt so aktuell. Das stärkste Argument für ORMs war immer der Komfort für Entwickler. SQL ist ausführlich und fehleranfällig. Die meisten schreiben es ungern von Hand. Dieses Argument löst sich gerade auf.
KI-Agenten schreiben SQL mühelos und deutlich besser als ORM-Code. Der Grund ist einfach: Im Netz gibt es um Größenordnungen mehr rohes SQL als Aufrufe der Hibernate Criteria API oder Prisma-Abfragen. SQL ist universell. Jede Datenbank dokumentiert es, jede Antwort auf Stack Overflow nutzt es, jedes Lehrbuch lehrt es. ORM-DSLs dagegen sind über Hersteller und Versionen zersplittert. Für sie gibt es weit weniger Trainingsdaten und weit mehr Mehrdeutigkeit.
Bei Interlusion gehört es zum normalen Entwicklungsablauf, dass Agenten Abfragen erzeugen, sie anhand von Ausführungsplänen optimieren und typsicheren Datenbankcode schreiben. Mit rohem SQL gelingt ihnen das besser und schneller als mit jeder ORM-Abstraktion, weil zwischen Absicht und Ergebnis weniger Umwege liegen. Der Komfortvorsprung von „ORM-Aufruf schreiben“ gegenüber „echtes SQL schreiben“ ist nicht nur geschrumpft. Er hat sich umgekehrt. SQL ist heute der einfachere Weg.
Damit kippt die ganze Rechnung. Wenn der letzte Vorteil eines ORMs gesparte Tastenanschläge sind und ein Agent diesen Vorteil wegnimmt, was bleibt dann? Eine Abstraktionsschicht zur Laufzeit. Sie erzeugt unvorhersehbare Abfragen, kostet Latenz und bläht das Bundle auf. Und sie hindert Ihr Team daran, das System zu verstehen, von dem es abhängt.
Die pragmatische Antwort: Nutzen Sie die Datenbank direkt, überlassen Sie den Boilerplate den Agenten und stecken Sie die gewonnene Zeit in das Verständnis Ihres Datenmodells. Dieses Verständnis zahlt sich mit jedem Jahr mehr aus. Der Komfort eines ORMs nicht.
Hören Sie auf, reflexhaft zum ORM zu greifen
Der Standard sollte nicht „ein ORM dazunehmen“ heißen. Der Standard sollte heißen: SQL verwenden und nur dann abstrahieren, wenn die Zusammensetzung Ihrer Abfragen es wirklich verlangt.
Die Branche hat zwei Jahrzehnte lang die Vorstellung gepflegt, SQL sei für Anwendungsentwickler zu schwer. Ist es nicht. Es ist eine Fähigkeit wie jede andere. Und sie zahlt sich jedes Mal aus, wenn nachts um drei eine Abfrage in Produktion lahmt und jemand verstehen muss, warum.
Verstecken Sie sich nicht länger vor Ihrer Datenbank. Sie ist der wichtigste Teil Ihres Systems.
Sie bauen etwas Datenintensives und wollen die Architektur von Anfang an richtig aufsetzen? Sprechen wir darüber.