Drizzle ORM für TypeScript SaaS: Schema-Design, Migrationen und warum es Prisma bei manchen Projekten schlägt

Sandor Farkas
Gründer & Lead Developer
Experte für Softwareentwicklung und Legacy-Code-Optimierung
LinkedInFrag fünf TypeScript-Teams, welches ORM sie nutzen, und du bekommst eine Debatte, und in letzter Zeit heißt diese Debatte Drizzle ORM vs Prisma. Prisma war jahrelang die Standardwahl für Next.js-SaaS-Projekte. Drizzle ist die neuere Option und gewinnt Teams für sich, denen vorhersagbares SQL und Edge-Deployments wichtig sind. Wir haben in Kundenprojekten mit beiden gearbeitet, und jedes von beiden passt besser zu einer anderen Art von Team. Dieser Beitrag zeigt, wo Drizzle Prisma schlägt, wo Prisma weiterhin gewinnt und wie Schema-Design und Migrationen für dasselbe Multi-Tenant-Schema in beiden aussehen.
Warum sich die ORM-Entscheidung schwer rückgängig machen lässt
Ein ORM berührt jede Query in deiner Anwendung. Es später auszutauschen bedeutet, den Datenzugriffscode neu zu schreiben und das Query-Verhalten unter Last neu zu verifizieren, während das Team seine Gewohnheiten umlernt. Kaum ein SaaS-Team tut das je, außer etwas läuft richtig schief. Das macht dies zu einer der wenigen Abhängigkeiten, die man vorab sorgfältig bewerten sollte, statt zu nehmen, was das Starter-Template mitliefert.
Wenn du unsicher bist, wie diese Entscheidung in deine Gesamtarchitektur passt: Unsere Arbeit zu Tech-Stack-Strategie behandelt genau diese Art von Abwägung.
Drizzle ORM vs Prisma: wo Drizzle vorne liegt
Die Kurzfassung: Drizzle bleibt nah am SQL, und diese Nähe zahlt sich in einigen praktischen Bereichen aus.
Vorhersagbare Queries
Prisma sitzt als Abstraktionsschicht zwischen deinem Code und der Datenbank. Du schreibst prisma.user.findMany({ include: { posts: true } }), und Prisma entscheidet, wie die Daten geholt werden. Meistens macht es das ordentlich. Wenn nicht, merkst du es in Produktion, meist als unerwartete Join-Strategie oder als Query, die weit mehr lädt als beabsichtigt.
Drizzle erzeugt SQL, das du aus dem geschriebenen Code vorhersagen kannst. Ein db.select().from(users).leftJoin(posts, eq(posts.userId, users.id)) produziert den Join, den du von Hand schreiben würdest. Wenn wir Performance-Audits auf SaaS-Backends fahren, sind unerklärliche Query-Muster aus ORM-Interna ein wiederkehrender Befund. Bei Drizzle gibt es schlicht weniger Magie zu auditieren.
Das Schema als einzige Quelle der Wahrheit für Typen
Prisma hält das Schema in einer separaten schema.prisma-Datei mit eigener DSL. Du führst prisma generate aus und bekommst einen TypeScript-Client heraus. Das funktioniert, aber der generierte Client ist ein Build-Artefakt, und die DSL ist eine weitere Sprache, die das Team kennen muss.
Drizzle definiert das Schema in TypeScript. Typen werden direkt aus der Schema-Definition abgeleitet, ohne Codegenerierungs-Schritt:
export const tenants = pgTable('tenants', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name').notNull(),
plan: text('plan', { enum: ['starter', 'growth', 'enterprise'] }).notNull(),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
tenantId: uuid('tenant_id').references(() => tenants.id).notNull(),
email: text('email').notNull(),
}, (t) => [uniqueIndex('users_tenant_email_idx').on(t.tenantId, t.email)]);
Der abgeleitete Typ einer tenants-Zeile aktualisiert sich in dem Moment, in dem du diese Datei bearbeitest. Es gibt keine Drift zwischen Schema und Typen, weil sie dasselbe sind.
Das Prisma-Äquivalent liest sich kürzer, lebt aber in einer eigenen Welt:
model Tenant {
id String @id @default(uuid())
name String
plan Plan
createdAt DateTime @default(now())
users User[]
}
model User {
id String @id @default(uuid())
tenant Tenant @relation(fields: [tenantId], references: [id])
tenantId String
email String
@@unique([tenantId, email])
}
Für ein Multi-Tenant-SaaS zählt der zusammengesetzte Unique-Index auf (tenantId, email): Beide ORMs können ihn ausdrücken, aber in Drizzle siehst du den tatsächlichen Indexnamen, der in PostgreSQL existieren wird. Dieses Detail ist an dem Tag nützlich, an dem du einen langsamen Query-Plan liest.
Edge-Runtimes
Drizzle läuft ohne Sonderaufwand in Cloudflare Workers und Vercel Edge Functions, weil es eine dünne Schicht über einem Datenbanktreiber ist. Prisma brauchte historisch seine Query-Engine-Binary, die auf Edge-Runtimes nicht läuft. Prisma schließt diese Lücke mit Driver-Adaptern, aber die Konfiguration ist weiterhin aufwändiger, und die Edge-Story bleibt ein Grund, warum Teams bei neuen Projekten Drizzle wählen. Wenn ein Teil deiner Next.js-App auf der Edge läuft, beseitigt Drizzle eine ganze Kategorie von Deployment-Reibung.
Migrationen, die man reviewen kann
Drizzle Kit difft dein TypeScript-Schema gegen die Datenbank und schreibt einfache SQL-Migrationsdateien. Dein Team reviewt die tatsächlichen ALTER TABLE-Statements im Pull Request. Prisma Migrate produziert unter der Haube ebenfalls SQL, aber der Workflow schiebt dich dahin, Migrationen als generierten Output statt als reviewten Code zu behandeln. Auf Produktionssystemen wollen wir, dass ein Mensch jedes DDL-Statement liest, bevor es ausgeliefert wird. Einfache SQL-Dateien machen diese Gewohnheit im Code Review leicht durchsetzbar.
Wo Prisma weiterhin gewinnt
Drizzle ist nicht für jedes Team die richtige Antwort.
Prismas Dokumentation und Ökosystem sind deutlich reifer. Ein Junior-Entwickler kann mit Prisma an einem Tag produktiv werden, weil fast jede Frage einen beantworteten Stack-Overflow-Thread hat und die Docs exzellent sind. Drizzles Dokumentation ist besser geworden, setzt aber weiterhin voraus, dass du dich mit SQL wohlfühlst. Wenn dein Team das nicht tut, leistet Prismas Abstraktion echte Arbeit für dich.
Prisma Studio ist eine nützliche GUI, um Daten während der Entwicklung zu inspizieren und zu bearbeiten. Drizzle Studio existiert und holt auf, aber Prismas Tooling ist polierter.
Auch die Relation-Query-API von Prisma ist bei tief verschachtelten Reads ergonomischer. Einen Tenant mit seinen Usern, deren Posts und den Kommentaren jedes Posts zu laden ist ein lesbarer Prisma-Call. In Drizzle nutzt du entweder die relationale Query-Erweiterung oder schreibst die Joins selbst, und die Joins werden langatmig.
Es gibt auch einen Staffing-Aspekt. Mehr Entwickler kennen Prisma. Wenn du häufig einstellst und Juniors onboardest, hat diese Vertrautheit einen Preisvorteil, der in keinem Benchmark auftaucht.
Wie wir es in Kundenprojekten entscheiden
Das Muster, das wir in der Praxis sehen, auch in unseren eigenen Custom-Software-Development-Projekten:
Wähle Drizzle, wenn dein Team flüssig SQL schreibt, wenn Query-Performance ein bekanntes Thema ist, wenn du auf Edge-Runtimes deployst oder wenn Migrationen als einfaches SQL reviewt werden sollen. Multi-Tenant-B2B-SaaS mit echter Query-Komplexität landet öfter hier als nicht.
Wähle Prisma, wenn das Team gemischt erfahren ist, das Produkt früh ist, das Datenmodell noch stark rotiert und die Onboarding-Geschwindigkeit der Entwickler wichtiger ist, als die letzten Millisekunden aus Queries zu holen. Ein Startup vor Product-Market-Fit profitiert meist mehr von Prismas Leitplanken als von Drizzles Kontrolle.
Keine der beiden Entscheidungen ist falsch. Der Fehler ist, per Beliebtheitswettbewerb zu wählen, statt das Werkzeug auf das Team abzustimmen, das du tatsächlich hast.
Ein bestehendes Prisma-Projekt migrieren
Wenn du Prisma bereits in Produktion betreibst und die genannten Schmerzpunkte spürst, rechtfertigt das allein selten einen kompletten Rewrite. Die Migration kann inkrementell laufen: Beide ORMs können gegen dieselbe Datenbank koexistieren, deshalb ziehen Teams typischerweise zuerst die heißesten Query-Pfade auf Drizzle um und lassen stabilen CRUD-Code auf Prisma. drizzle-kit pull kann deine bestehende Datenbank introspektieren und das Drizzle-Schema als Startpunkt generieren, was den Großteil der manuellen Abschreibarbeit beseitigt.
Wir haben diese Art inkrementeller Migration im Rahmen von Legacy Code Optimierung begleitet. Die Hauptrisiken sind subtile Verhaltensunterschiede beim Transaktions-Handling und bei Null-Semantik. Lege also Integrationstests um die Query-Pfade, die du umziehst, bevor du sie umziehst.
Eine Anmerkung zu Benchmarks
Du wirst Benchmarks finden, die Drizzle um ein Mehrfaches schneller zeigen als Prisma. Geh vorsichtig damit um. Der Großteil der Lücke kommt aus Prismas Engine-Overhead pro Query, der bei hochfrequenten kleinen Queries zählt und bei einem Dashboard, das eine Handvoll schwererer Queries pro Request fährt, viel weniger. Benchmarke deinen eigenen Workload, bevor ein Chart eine Architekturentscheidung für dich trifft. Wenn du ein zweites Paar Augen für diese Analyse willst: Das ist das Kerngeschäft unseres Code Quality Consulting.
Die Entscheidung für dein Team
Die Frage Drizzle ORM vs Prisma läuft darauf hinaus, wie viel Abstraktion du zwischen deinem TypeScript und deiner Datenbank willst. Drizzle gibt dir Kontrolle, vorhersagbares SQL, reviewbare Migrationen und Edge-Kompatibilität. Prisma gibt dir Ergonomie, reifes Tooling und eine sanftere Lernkurve. Starke SQL-Teams, die ernsthafte Multi-Tenant-Produkte bauen, sind auf Drizzle tendenziell glücklicher. Teams, die auf Onboarding-Geschwindigkeit optimieren, sind es auf Prisma.
Wenn du diese Entscheidung für einen neuen Build abwägst oder eine Migration weg von einem der beiden ORMs erwägst, schauen wir uns deine konkrete Situation gerne an. Schreib an hello@wolf-tech.io oder finde uns auf wolf-tech.io.
