Prisma ORM mit Claude Code: TypeScript-Datenbankzugriff 2026
Prisma ist das modernste ORM für Node.js und TypeScript — vollständige Typ-Sicherheit, Auto-Completion, einfache Migrations. Claude Code kennt Prisma in- und auswendig: Schema-Design, komplexe Queries, Performance-Optimierung und sichere Migrations.
Prisma Setup und Schema-Design
SchemaDatenmodell mit Claude Code entwerfen
# Prompt: "Entwirf Prisma-Schema für eine SaaS-App mit:
# Users, Organizations (Multi-Tenancy), Projects, Tags (M:N)
# Soft-Delete für alle Hauptentitäten"
# schema.prisma — Claude Code generiert:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
deletedAt DateTime? // Soft Delete
memberships OrgMembership[]
@@index([email])
@@map("users")
}
model Organization {
id String @id @default(cuid())
name String
slug String @unique
plan Plan @default(FREE)
createdAt DateTime @default(now())
deletedAt DateTime?
members OrgMembership[]
projects Project[]
@@map("organizations")
}
model OrgMembership {
userId String
orgId String
role Role @default(MEMBER)
user User @relation(fields: [userId], references: [id])
org Organization @relation(fields: [orgId], references: [id])
@@id([userId, orgId]) // Composite PK
}
model Project {
id String @id @default(cuid())
name String
orgId String
createdAt DateTime @default(now())
deletedAt DateTime?
org Organization @relation(fields: [orgId], references: [id])
tags ProjectTag[]
@@index([orgId, deletedAt])
}
// Many-to-Many via explizite Zwischentabelle
model Tag {
id String @id @default(cuid())
name String
projects ProjectTag[]
}
model ProjectTag {
projectId String
tagId String
project Project @relation(fields: [projectId], references: [id])
tag Tag @relation(fields: [tagId], references: [id])
@@id([projectId, tagId])
}
enum Plan { FREE PRO ENTERPRISE }
enum Role { OWNER ADMIN MEMBER }
Migrations: Sicher in Production
MigrationWorkflow für Production-Migrations
# Development: Migration erstellen
npx prisma migrate dev --name add_user_avatar
# Production: Migration anwenden (KEIN migrate dev!)
npx prisma migrate deploy
# Schema-Änderungen die Claude Code sicher generiert:
# ✅ Neue Tabelle hinzufügen
# ✅ Nullable Spalte hinzufügen
# ✅ Index hinzufügen (mit CONCURRENTLY-Hinweis)
# ⚠️ NOT NULL Spalte auf bestehender Tabelle → Backfill nötig!
# ⚠️ Spalte umbenennen → Daten-Verlust-Risiko → Claude warnt!
# NOT NULL ohne Downtime — 3-Schritt-Migration:
# 1. Spalte als nullable hinzufügen
# 2. Backfill: UPDATE users SET avatar_url = '' WHERE avatar_url IS NULL
# 3. NOT NULL Constraint hinzufügen (separate Migration)
Production-Migration Regel: Niemals
prisma migrate dev in Production. Immer prisma migrate deploy. Claude Code kennt diesen Unterschied und warnt aktiv — nutze es.Queries: Von einfach bis komplex
QueriesRelations, Filtering, Aggregation
# Prompt: "Lade alle aktiven Projects einer Org mit Tags und Member-Count"
const projects = await prisma.project.findMany({
where: {
orgId,
deletedAt: null, // Soft-Delete Filter
name: { contains: search, mode: 'insensitive' }
},
include: {
tags: {
include: { tag: true } // M:N via Zwischentabelle
},
_count: {
select: { members: true } // Aggregate ohne extra Query
}
},
orderBy: { createdAt: 'desc' },
take: 20,
skip: (page - 1) * 20 // Pagination
});
# Upsert: Create oder Update in einem Call
await prisma.orgMembership.upsert({
where: { userId_orgId: { userId, orgId } },
create: { userId, orgId, role: 'MEMBER' },
update: { role: 'ADMIN' }
});
# Raw Query wenn Prisma nicht ausreicht:
const result = await prisma.$queryRaw`
SELECT org_id, COUNT(*) as project_count
FROM projects
WHERE deleted_at IS NULL
GROUP BY org_id
HAVING COUNT(*) > 10
`;
Transactions: Atomare Operationen
# Prompt: "Erstelle einen User und seine Default-Organization atomar"
async function createUserWithOrg(email, name, orgName) {
return prisma.$transaction(async (tx) => {
// tx = transaktionaler Prisma-Client
const user = await tx.user.create({
data: { email, name }
});
const org = await tx.organization.create({
data: {
name: orgName,
slug: slugify(orgName) + '-' + nanoid(4),
members: {
create: { userId: user.id, role: 'OWNER' }
}
}
});
return { user, org };
});
// Bei Fehler: automatischer Rollback!
}
Performance-Optimierung
PerformanceN+1-Problem und Query-Optimierung
# N+1 Problem — Claude Code erkennt und fixt:
# SCHLECHT: Eine Query pro Project für Tags
for (const project of projects) {
project.tags = await prisma.projectTag.findMany({ where: { projectId: project.id } });
}
# 100 Projects = 101 Queries!
# GUT: Alles in einer Query mit include
const projects = await prisma.project.findMany({
include: { tags: { include: { tag: true } } }
});
# 1 Query — Prisma batcht automatisch
# Connection Pool für Production (nicht Standard!):
# DATABASE_URL="postgresql://...?connection_limit=10&pool_timeout=20"
# Oder: Prisma Accelerate für globales Connection Pooling
# Query-Logging für Performance-Analyse:
const prisma = new PrismaClient({
log: ['query', 'slow_query'],
// slow_query: Queries > 1000ms loggen
});
Prisma Prompt-Tipp: "Analysiere diese Prisma-Queries auf N+1-Probleme und fehlende Indizes. Zeige die optimierte Version." Claude Code erkennt typische Muster und schlägt include-basierte Lösungen vor.
Datenbank-Modul im Kurs
Im Claude Code Mastery Kurs: vollständiges Prisma-Modul mit Schema-Design, Production-Migrations, komplexen Relations, Transactions und Performance-Optimierung — inkl. N+1-Problem-Erkennung und Query-Analyse.
14 Tage kostenlos testen →