Design wechseln

Drizzle ORM Praxisleitfaden: 90 % leichter als Prisma – die TypeScript-ORM-Wahl

Easton editorial illustration: component assembly loom

Letzte Woche Deployment auf Vercel – Startseite 3 Sekunden Wartezeit. Drei Sekunden! Nutzer sind längst weg.

Im Vercel-Bundle-Analyse: ein Prisma-Client-Paket mit 14 MB. Einfache User-Queries – warum so viel Code? Schlimmer: Lambda Cold Start quälend – Funktionen ohne Prisma ~600 ms, mit Prisma 2,5 Sekunden.

Prisma sei doch gut? Stimmt – auch ich dachte das. Typsicherheit, Auto-Migration, Prisma Studio – alles da. Aber: es ist zu schwer.

Kennen Sie das? Serverless mit langsamem Cold Start, Bundle über Limit, komplexe Queries nur mit Raw SQL – dann ist dieser Artikel für Sie. Drizzle ORM: Kernpaket 7,4 kb, über 90 % leichter als Prisma, gleiche Typsicherheit.

Wir konfigurieren Next.js + Drizzle von null, erklären die SQL-like API und vergleichen Performance mit Prisma. Und: wann Drizzle, wann weiter Prisma.

Warum Drizzle? Schmerzpunkte bestehender ORMs

Drei Prisma-Schmerzpunkte

Prisma passt in vielen Fällen – aber drei Probleme bleiben hartnäckig.

Schmerzpunkt 1: Bundle außer Kontrolle

Prisma v5 Client bis 14 MB. Ihr ganzes Next.js-Projekt vielleicht 2–3 MB – Prisma allein fast die Hälfte. Prisma 7 reduziert auf ~1 MB (ohne Rust-Binary) – alte Versionen oder Bundle-Sensibilität bleiben kritisch.

Unser Echtzeit-Chat auf Cloudflare Workers: Limit 1 MB. Prisma scheiterte. Plan B nötig.

Schmerzpunkt 2: Langsamer Serverless Cold Start

GitHub Issue #10724 – jahrelang diskutiert: Prisma Lambda Cold Start zu langsam.

  • Ohne ORM: ~600 ms
  • Prisma v5: ~2,5 s
  • Prisma v7: ~1,5 s (besser, aber noch langsam)

Ursache: Parsen eines riesigen DMMF-Strings beim Start. Mittlere Schemas: über 6 Mio. Zeichen – jeder Cold Start erneut.

Cal.com schrieb deshalb einen Blogpost zur Cold-Start-Optimierung. Fazit: Problem real, nur Workarounds.

Schmerzpunkt 3: Wenig SQL-Kontrolle

Prisma abstrahiert SQL – DSL statt SQL. Meist praktisch – bei komplexen Queries nicht.

Mehrstufige JOINs, Subqueries, bedingte Aggregation – Prisma API reicht oft nicht. Dann prisma.$queryRaw und handgeschriebenes SQL.

Warum nicht von Anfang an SQL-nah? Drizzles Ansatz.

Was Entwickler wirklich wollen

  1. Typsicherheit ohne Performance-Opfer
  2. SQL nutzen, keine neue DSL
  3. Serverless-tauglich (Vercel, Cloudflare Workers, Lambda)
  4. Schnelle Kompilierung – Prisma-Typen bremsen große Projekte

Drizzle zielt genau darauf.

Was ist Drizzle ORM? Kernmerkmale

Design-Philosophie

Slogan: „If you know SQL, you know Drizzle.“ – zutreffend.

"If you know SQL, you know Drizzle."

Klassische ORMs verstecken SQL. Drizzle nicht – TypeScript-API nahe an SQL, volle Typ-Hinweise.

Beispiel:

// Drizzle Query
await db
  .select()
  .from(posts)
  .leftJoin(comments, eq(posts.id, comments.postId))
  .where(eq(posts.id, 10))

// Generiertes SQL
SELECT * FROM posts
LEFT JOIN comments ON posts.id = comments.post_id
WHERE posts.id = 10

Struktur fast identisch mit SQL. Wer SQL kann, versteht es sofort.

Kernmerkmale

1. Extrem leicht

Kernpaket drizzle-orm: 7,4 kb (min+gzip), null Runtime-Abhängigkeiten.

  • Drizzle: ~7,4 kb
  • TypeORM: ~300 kb
  • Prisma v7: ~1 MB
  • Prisma v5: ~14 MB

Keine Größenordnung gleich.

2. TypeScript-First, kein Client-Generate

Prisma: prisma generate. Drizzle: nicht nötig.

Schema definieren – TypeScript inferiert Typen. IntelliSense, Typ-Checks, Fehler zur Compile-Zeit.

3. SQL-like API, Lernkosten nahe null

Mit SQL: unter 10 Minuten Einstieg.

// SELECT
db.select().from(users).where(eq(users.id, 1))

// INSERT
db.insert(users).values({ name: 'John', email: '[email protected]' })

// UPDATE
db.update(users).set({ name: 'Jane' }).where(eq(users.id, 1))

// DELETE
db.delete(users).where(eq(users.id, 1))

Wer SQL kann, braucht keine Docs.

4. Performance ohne Abstraktionskosten

Keine Runtime-Abstraktion – Queries werden direkt zu SQL. Kein DMMF-Parsing wie bei Prisma. Keine versteckten Kosten.

5. Serverless-Ready

Umgebungen:

  • Vercel Edge Functions
  • Cloudflare Workers
  • AWS Lambda
  • Deno Deploy
  • Bun

Serverless-DB-Treiber:

  • Neon Serverless
  • PlanetScale
  • Turso (SQLite on the Edge)
  • Supabase

Unser Stack: Neon + Drizzle auf Vercel Edge – Cold Start 2,5 s → 700 ms.

Einsatzszenarien

1. Serverless

Lambda, Edge – Leichtgewicht und schneller Cold Start sind Pflicht.

2. Performancekritisch

Echtzeit, Finanz, Analytics – null Abstraktion zahlt sich aus.

3. Komplexe SQL-Kontrolle

Viele komplexe Queries, manuelle Optimierung – SQL-like schlägt Prisma DSL.

4. Bundle-sensitive Full-Stack-Projekte

SolidStart, Qwik – ORM im Client-Bundle. 7,4 kb vs. Megabytes.

Umgekehrt: wenig SQL im Team, schnelle Prototypen, Prisma Studio/Migrate/Pulse – Prisma kann besser passen.

Next.js + Drizzle: Praxis-Setup

Theorie reicht – wir bauen Next.js 15 + Drizzle + PostgreSQL von null.

Umgebung vorbereiten

Next.js-Projekt:

npx create-next-app@latest my-drizzle-app
cd my-drizzle-app

Drizzle-Abhängigkeiten:

npm install drizzle-orm drizzle-kit
npm install @neondatabase/serverless  # für Neon
# oder
npm install postgres  # klassisches PostgreSQL

Empfehlung: Neon – serverless PostgreSQL, ideal mit Drizzle. Gratis-Account, DB anlegen, Connection String kopieren.

Datenbank-Schema definieren

db/schema.ts:

import { pgTable, serial, text, timestamp, integer } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';

// Benutzertabelle
export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  createdAt: timestamp('created_at').defaultNow(),
});

// Artikeltabelle
export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  content: text('content'),
  authorId: integer('author_id').references(() => users.id),
  createdAt: timestamp('created_at').defaultNow(),
});

// Relationen (1:n)
export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}));

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, {
    fields: [posts.authorId],
    references: [users.id],
  }),
}));

Reines TypeScript – kein Prisma-Schema, kein Client-Generate.

Datenbankverbindung

db/index.ts:

import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';

const sql = neon(process.env.DATABASE_URL!);

export const db = drizzle(sql, { schema });

In .env.local:

DATABASE_URL=postgres://user:[email protected]/dbname

Drizzle Kit (Migrationen)

drizzle.config.ts:

import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  schema: './db/schema.ts',
  out: './drizzle',
  dialect: 'postgresql',
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

Migration erzeugen:

npx drizzle-kit generate

SQL in drizzle/ prüfen, dann:

npx drizzle-kit push

Tabellen stehen.

Projektstruktur

my-drizzle-app/
├── app/                  # Next.js App
│   ├── page.tsx
│   └── actions.ts        # Server Actions
├── db/
│   ├── schema.ts         # Tabellen und Relationen
│   └── index.ts          # DB-Verbindung
├── drizzle/
│   └── migrations/       # Migrationen (auto)
├── drizzle.config.ts     # Drizzle Kit Config
├── .env.local            # Umgebungsvariablen
└── package.json

Unter 5 Minuten – kein Prisma-Schema-Syntax, kein langes prisma generate, nur TypeScript.

Drizzle SQL-like API in der Praxis

Häufigste Operationen und Server Actions.

Basis-CRUD

SELECT

import { db } from '@/db';
import { users, posts } from '@/db/schema';
import { eq, like, and, or, desc } from 'drizzle-orm';

// Alle Benutzer
const allUsers = await db.select().from(users);

// Ein Benutzer
const user = await db.select().from(users).where(eq(users.id, 1));

// LIKE-Suche
const result = await db.select().from(users).where(like(users.name, '%John%'));

// Mehrere Bedingungen
const admins = await db
  .select()
  .from(users)
  .where(
    and(
      eq(users.role, 'admin'),
      gt(users.createdAt, new Date('2024-01-01'))
    )
  );

// Sortierung und Limit
const latestPosts = await db
  .select()
  .from(posts)
  .orderBy(desc(posts.createdAt))
  .limit(10);

SQL-Logik als Funktionsaufrufe.

INSERT

// Ein Datensatz
await db.insert(users).values({
  name: 'John Doe',
  email: '[email protected]',
});

// Mehrere
await db.insert(users).values([
  { name: 'Alice', email: '[email protected]' },
  { name: 'Bob', email: '[email protected]' },
]);

// Mit Rückgabe
const [newUser] = await db
  .insert(users)
  .values({ name: 'Charlie', email: '[email protected]' })
  .returning();

console.log(newUser.id);

UPDATE

await db
  .update(users)
  .set({ name: 'Jane Doe' })
  .where(eq(users.id, 1));

await db
  .update(posts)
  .set({ published: true })
  .where(eq(posts.authorId, 1));

const [updatedUser] = await db
  .update(users)
  .set({ name: 'Updated Name' })
  .where(eq(users.id, 1))
  .returning();

DELETE

await db.delete(users).where(eq(users.id, 1));

await db.delete(posts).where(eq(posts.published, false));

const deleted = await db
  .delete(users)
  .where(eq(users.id, 1))
  .returning();

Erweiterte Queries

JOIN

const usersWithPosts = await db
  .select({
    userId: users.id,
    userName: users.name,
    postId: posts.id,
    postTitle: posts.title,
  })
  .from(users)
  .leftJoin(posts, eq(users.id, posts.authorId));

const activeAuthors = await db
  .select()
  .from(users)
  .innerJoin(posts, eq(users.id, posts.authorId));

Subquery

const sq = db
  .select({ authorId: posts.authorId, count: count() })
  .from(posts)
  .groupBy(posts.authorId)
  .having(gt(count(), 5))
  .as('sq');

const prolificAuthors = await db
  .select()
  .from(users)
  .innerJoin(sq, eq(users.id, sq.authorId));

Aggregation

import { count, sum, avg } from 'drizzle-orm';

const [{ total }] = await db
  .select({ total: count() })
  .from(users);

const postCounts = await db
  .select({
    authorId: posts.authorId,
    count: count(),
  })
  .from(posts)
  .groupBy(posts.authorId);

In Next.js Server Actions

app/actions.ts:

'use server';

import { db } from '@/db';
import { users } from '@/db/schema';
import { eq } from 'drizzle-orm';
import { revalidatePath } from 'next/cache';

export async function createUser(formData: FormData) {
  const name = formData.get('name') as string;
  const email = formData.get('email') as string;

  try {
    await db.insert(users).values({ name, email });
    revalidatePath('/users');
    return { success: true };
  } catch (error) {
    return { success: false, error: 'Benutzer konnte nicht erstellt werden' };
  }
}

export async function getUsers() {
  return await db.select().from(users);
}

export async function deleteUser(id: number) {
  try {
    await db.delete(users).where(eq(users.id, id));
    revalidatePath('/users');
    return { success: true };
  } catch (error) {
    return { success: false, error: 'Benutzer konnte nicht gelöscht werden' };
  }
}

Seite:

// app/users/page.tsx
import { getUsers } from '../actions';

export default async function UsersPage() {
  const users = await getUsers();

  return (
    <div>
      <h1>Benutzerliste</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            {user.name} - {user.email}
          </li>
        ))}
      </ul>
    </div>
  );
}

TypeScript Typsicherheit

Volle Typ-Inferenz – Drizzles Stärke.

const users = await db.select().from(users);
// Typ: { id: number; name: string; email: string; createdAt: Date }[]

const result = await db
  .select({
    id: users.id,
    name: users.name,
  })
  .from(users);
// Typ: { id: number; name: string }[]

await db.select().from(users).where(eq(users.id, '1'));
// ❌ TypeScript: string nicht zu number zuweisbar

IntelliSense für Felder, Funktionen, Operatoren. TypeScript-Compiler als Dokumentation.

Drizzle vs. Prisma: Tiefer Vergleich

Objektiv – damit Sie die richtige Wahl treffen.

Performance

~7.4kb
Drizzle Bundle
vs. Prisma 14 MB
~600ms
Cold Start
vs. Prisma 2,5 s
0
Runtime-Abhängigkeiten
Reines TypeScript
Source: Produktions-Monitoring
DimensionDrizzlePrisma v5Prisma v7Anmerkung
Bundle~7,4 kb~14 MB~1 MBDrizzle am leichtesten
Cold Start~600 ms~2,5 s~1,5 sServerless
Runtime-Deps0Rust-Binary0Drizzle & v7 ohne Binary
Speicher~5 MB~80 MB~30 MB (geschätzt)Laufzeit
Typ-Check-GeschwindigkeitSchnellMittelMittelEinfachere Inferenz

Reale Fallzahlen

Migration Prisma v5 → Drizzle:

  • Erste Anfrage: 3 s → 700 ms (76 % schneller)
  • Produktions-Bundle: 18 MB → 4 MB (78 % kleiner)
  • Lambda Cold Start: 2,4 s → 650 ms (73 % schneller)

Produktions-Monitoring, keine Labortricks.

Developer Experience

Schema

// Drizzle (TypeScript)
export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
});

// Prisma (DSL)
model User {
  id   Int    @id @default(autoincrement())
  name String
}

Drizzle: natives TypeScript, IDE, Generics, Conditional Types.

Prisma: kompakteres Schema, bessere Lesbarkeit.

Query-Stil

// Drizzle (SQL-like)
await db
  .select()
  .from(users)
  .leftJoin(posts, eq(users.id, posts.authorId))
  .where(gt(posts.views, 1000));

// Prisma (Chain-API)
await prisma.user.findMany({
  include: {
    posts: {
      where: { views: { gt: 1000 } },
    },
  },
});

Drizzle: näher an SQL, komplexe Queries leichter.

Prisma: ohne SQL-Hintergrund einfacher, verschachtelte Queries klarer.

Funktionsvergleich

Drizzle

  1. Extrem leicht (7,4 kb)
  2. Serverless-native, schneller Cold Start
  3. Starke SQL-Kontrolle
  4. Kein Client-Generate
  5. Tree-shakable

Prisma

  1. Reife Ökosystem (seit 2021)
  2. Prisma Studio, Migrate, Pulse
  3. Intelligentere Relationen, weniger N+1
  4. Einsteigerfreundlicher
  5. Detailliertere Laufzeitfehler

Auswahl-Empfehlung

Drizzle

✅ Serverless/Edge (Vercel, Cloudflare Workers, Deno Deploy)
✅ Performancekritisch (Echtzeit, Finanz, High-Traffic-API)
✅ Bundle-Limit (< 1 MB)
✅ SQL-erfahrenes Team
✅ Komplexe SQL-Optimierung

Prisma

✅ Wenig SQL im Team
✅ DX und Toolchain wichtig
✅ Prisma Studio gewünscht
✅ Komplexe Relationen und Modellierung
✅ Kein Serverless, Bundle unkritisch

Persönliche Empfehlung

  • Side Project / Startup: Drizzle (Performance, Kosten)
  • Enterprise / Team: SQL stark → Drizzle; schwach → Prisma
  • Serverless-First: klar Drizzle
  • Klassischer Server: beides; Prisma-Toolchain reifer

Hybrid: performancekritische Module Drizzle, Admin Prisma – parallel möglich.

Migration und Best Practices

Von Prisma zu Drizzle

Progressiv starten.

Schritt 1: Schema

// Prisma
model User {
  id        Int      @id @default(autoincrement())
  name      String
  email     String   @unique
  posts     Post[]
  createdAt DateTime @default(now())
}

// Drizzle
export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  createdAt: timestamp('created_at').defaultNow(),
});

Schritt 2: Queries

// Prisma
const user = await prisma.user.findUnique({
  where: { id: 1 },
  include: { posts: true },
});

// Drizzle
const [user] = await db
  .select()
  .from(users)
  .where(eq(users.id, 1))
  .leftJoin(posts, eq(users.id, posts.authorId));

Schritt 3: Parallel betreiben

import { db } from '@/db/drizzle';
const latestPosts = await db
  .select()
  .from(posts)
  .orderBy(desc(posts.createdAt))
  .limit(50);

import { prisma } from '@/db/prisma';
const userWithRelations = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: { include: { comments: { include: { author: true } } } },
  },
});

Schrittweise ersetzen.

Drizzle Best Practices

1. Connection Pool (Serverless)

import { drizzle } from 'drizzle-orm/neon-http';
import { neon, neonConfig } from '@neondatabase/serverless';

neonConfig.fetchConnectionCache = true;

const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });

2. Prepared Statements

import { db } from '@/db';
import { users } from '@/db/schema';
import { eq } from 'drizzle-orm';

const getUserById = db
  .select()
  .from(users)
  .where(eq(users.id, placeholder('id')))
  .prepare('get_user_by_id');

const user = await getUserById.execute({ id: 1 });

3. Transaktionen

await db.transaction(async (tx) => {
  const [user] = await tx
    .insert(users)
    .values({ name: 'John', email: '[email protected]' })
    .returning();

  await tx.insert(posts).values({
    title: 'First Post',
    authorId: user.id,
  });
});

4. Typen exportieren

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull(),
});

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;

import type { User } from '@/db/schema';

function UserCard({ user }: { user: User }) {
  return <div>{user.name}</div>;
}

5. Fehlerbehandlung

try {
  await db.insert(users).values({
    name: 'John',
    email: '[email protected]',
  });
} catch (error) {
  if (error.code === '23505') {
    console.error('E-Mail existiert bereits');
  } else {
    console.error('Datenbankfehler', error);
  }
}

Fazit

Drizzle ORM versteckt SQL nicht – es umarmt SQL. 7,4 kb, null Runtime-Deps, nahezu native SQL-Performance: Leichtgewicht ist kein Kompromiss, sondern oft die bessere Wahl.

Kein vollständiger Prisma-Ersatz – Prisma hat reifere Tools und besseren Einsteigerweg. Aber bei Serverless, Performance- und Bundle-Druck, komplexem SQL und SQL-erfahrenem Team: Drizzle passt oft besser.

Unsere Zahlen: Cold Start 73 % schneller, Bundle 78 % kleiner, erste Anfrage 3 s → 700 ms. Kein Mikro-Tuning – ein Qualitätssprung.

Prisma-Cold-Start- oder Bundle-Frust? Drizzle testen – mit SQL in ~10 Minuten startklar.

Links:

Probieren Sie es – vielleicht kommen Sie, wie ich, nicht mehr zurück.

Next.js + Drizzle ORM: Vollständiges Setup und Migrationsleitfaden

Drizzle ORM von null: Umgebung, Schema, DB-Verbindung, Queries und schrittweise Migration von Prisma

Estimated time: PT2H

  1. 1

    Step 1: Schritt 1: Umgebung und Abhängigkeiten

    Next.js-Projekt:
  2. 2

    Step 2: Schritt 2: Schema definieren

    db/schema.ts:
  3. 3

    Step 3: Schritt 3: Verbindung und Drizzle Kit

    db/index.ts:
  4. 4

    Step 4: Schritt 4: SQL-like API

    Basis-CRUD:
  5. 5

    Step 5: Schritt 5: Server Actions

    app/actions.ts:
  6. 6

    Step 6: {user.name}

    {user.email}
  7. 7

    Step 7: Schritt 6: Migration von Prisma (optional)

    Schema:

FAQ

Was unterscheidet Drizzle ORM von Prisma? Wann sollte man Drizzle wählen?
Kernunterschiede:

Performance:
• Drizzle: 7,4 kb, Cold Start 600 ms, null Runtime-Abhängigkeiten
• Prisma v5: 14 MB, Cold Start 2,5 s, Rust-Binary nötig
• Prisma v7: 1 MB, Cold Start 1,5 s – optimiert, aber weiterhin langsamer als Drizzle

Developer Experience:
• Drizzle: SQL-like API, SQL-Kenntnisse reichen, kein Client-Generate nötig
• Prisma: eigene DSL, Lernaufwand, prisma generate erforderlich

Drizzle wählen:
✅ Serverless/Edge (Vercel, Cloudflare Workers, Deno Deploy)
✅ Performancekritisch (Echtzeit, Finanzsysteme, High-Traffic-APIs)
✅ Bundle-Limit (< 1 MB)
✅ Team mit SQL-Basis, direkte Query-Kontrolle
✅ Projekte mit komplexen SQL-Optimierungen

Prisma wählen:
✅ Team ohne SQL-Erfahrung, schneller Einstieg
✅ Fokus auf DX und vollständige Toolchain
✅ Visuelles DB-Management (Prisma Studio)
✅ Komplexe Relationen und Datenmodellierung
✅ Kein Serverless, Bundle-Größe unkritisch
Was bedeutet die SQL-like API von Drizzle ORM konkret?
Drizzles API soll TypeScript-Code möglichst nah an SQL halten:

Beispielvergleich:

SQL:
```sql
SELECT * FROM posts
LEFT JOIN comments ON posts.id = comments.post_id
WHERE posts.id = 10
```

Drizzle:
```typescript
await db
.select()
.from(posts)
.leftJoin(comments, eq(posts.id, comments.postId))
.where(eq(posts.id, 10))
```

Kernmerkmale:
• Code-Struktur fast identisch mit SQL
• Wer SQL kann, versteht die API sofort
• Lernkosten nahe null (bei SQL-Kenntnissen)
• Volle Typ-Inferenz, IntelliSense-Autovervollständigung
• Fehler schon zur Compile-Zeit

Vergleich Prisma DSL:
```typescript
// Prisma: neue Query-Syntax lernen
await prisma.user.findMany({
include: {
posts: {
where: { views: { gt: 1000 } },
},
},
});
```

Drizzle bleibt näher an nativem SQL – komplexe Queries lassen sich leichter ausdrücken.
Wie groß ist Drizzles Performance-Vorteil in Serverless-Umgebungen?
Reale Fallzahlen (Migration Prisma v5 → Drizzle):

Performance:
• Erste Anfrage: 3 s → 700 ms (76 % schneller)
• Produktions-Bundle: 18 MB → 4 MB (78 % kleiner)
• Lambda Cold Start: 2,4 s → 650 ms (73 % schneller)

Ursachen:

1. Bundle-Größe:
• Drizzle-Kern nur 7,4 kb (min+gzip)
• Prisma v5 Client bis 14 MB
• Cloudflare Workers u. a. mit 1-MB-Limit – Prisma scheitert dort

2. Cold Start:
• Prisma parst beim Start große DMMF-Strings (Data Model Meta Format)
• Mittlere Schemas: über 6 Mio. Zeichen
• Jeder Cold Start erneut – daher langsam
• Drizzle: keine Runtime-Abstraktion, direkte SQL-Übersetzung

3. Speicher:
• Drizzle: ~5 MB
• Prisma v5: ~80 MB
• Prisma v7: ~30 MB (geschätzt)

Monitoring-Daten aus Produktion, keine Labortricks.
Wie migriert man von Prisma zu Drizzle? Ist das komplex?
Progressiv möglich – kein Big-Bang nötig:

Schritt 1: Schema-Konvertierung

Prisma Schema → Drizzle Schema:
• model → pgTable
• Int → serial/integer, String → text, DateTime → timestamp
• Relationen: Prisma-Syntax → relations()

Schritt 2: Queries umschreiben

• findUnique/findMany → select().from().where()
• include → leftJoin/innerJoin
• create → insert().values()
• update → update().set().where()

Schritt 3: Schrittweise ersetzen

Prisma und Drizzle parallel:
```typescript
// Performancekritisch: Drizzle
import { db } from '@/db/drizzle';
const latestPosts = await db
.select()
.from(posts)
.orderBy(desc(posts.createdAt))
.limit(50);

// Komplexe Relationen vorerst Prisma
import { prisma } from '@/db/prisma';
const userWithRelations = await prisma.user.findUnique({
where: { id: 1 },
include: {
posts: { include: { comments: { include: { author: true } } } },
},
});
```

Schrittweise ersetzen, Risiko senken. Hauptsächlich Syntax-Umstellung.
Welche Datenbanken und Umgebungen unterstützt Drizzle ORM?
Datenbanken:

• PostgreSQL (Neon Serverless empfohlen)
• MySQL
• SQLite (inkl. Turso, SQLite on the Edge)
• SQL Server

Serverless-Umgebungen:

• Vercel Edge Functions
• Cloudflare Workers
• AWS Lambda
• Deno Deploy
• Bun

Native Serverless-Treiber:

• Neon Serverless (PostgreSQL)
• PlanetScale (MySQL)
• Turso (SQLite on the Edge)
• Supabase (PostgreSQL)

Unser Stack: Neon + Drizzle auf Vercel Edge – Cold Start von 2,5 s auf 700 ms.

Vorteile:
• Alle gängigen Serverless-Umgebungen
• Native Serverless-DB-Treiber
• Null Runtime-Abhängigkeiten – läuft überall mit JavaScript
Wie ist Drizzles Typsicherheit im Vergleich zu Prisma?
Drizzle bietet volle Typsicherheit – oft einfacher als Prisma:

Typ-Inferenz:

Drizzle (automatisch):
```typescript
// Rückgabetyp automatisch
const users = await db.select().from(users);
// Typ: { id: number; name: string; email: string; createdAt: Date }[]

// Felder wählen – Typ passt sich an
const result = await db
.select({
id: users.id,
name: users.name,
})
.from(users);
// Typ: { id: number; name: string }[]

// Compile-Fehler
await db.select().from(users).where(eq(users.id, '1'));
// ❌ TypeScript: string nicht zu number zuweisbar
```

Kernmerkmale:
• Kein Client-Generate, TypeScript inferiert direkt
• IntelliSense für Felder, Funktionen, Operatoren
• Fehler zur Compile-Zeit, nicht erst zur Laufzeit
• Schnellere Typ-Checks (einfachere Inferenz)

Prisma:
• prisma generate nötig
• Große Projekte: langsamere TS-Kompilierung
• Drizzle: schnellere Builds

Typen fürs Frontend:
```typescript
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
```
Ist Drizzle ORM für Einsteiger geeignet? Wie steil ist die Lernkurve?
Mit SQL-Kenntnissen sehr flach:

Einstieg:
• SQL-Kenntnisse: ~10 Minuten
• Ohne SQL: zuerst SQL-Grundlagen

Warum geringe Lernkosten:
• SQL-like API, Struktur wie SQL
• Keine neue DSL wie bei Prisma
• Volle Typ-Hinweise, IntelliSense
• TypeScript-Compiler als beste Dokumentation

Beispiele:
```typescript
// SELECT
db.select().from(users).where(eq(users.id, 1))

// INSERT
db.insert(users).values({ name: 'John', email: '[email protected]' })

// UPDATE
db.update(users).set({ name: 'Jane' }).where(eq(users.id, 1))

// DELETE
db.delete(users).where(eq(users.id, 1))
```

Wer SQL kann, braucht kaum Docs.

Prisma:
• Eigene DSL lernen
• Freundlicher ohne SQL-Hintergrund
• Mit SQL: Drizzle oft intuitiver

Empfehlung:
• Starkes SQL-Team: Drizzle
• Schwaches SQL: Prisma – oder SQL lernen, dann Drizzle

11 Min. Lesezeit · Veröffentlicht am: 20. Dez. 2025 · Aktualisiert am: 14. Juli 2026

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog