Drizzle vs Prisma vs Kysely: TypeScript ORM 2026
3 ORM/query-builder TS. Drizzle = TypeScript-first, lightweight. Prisma = mature, codegen-heavy. Kysely = type-safe SQL builder. Saya pakai keduanya, verdict beda.
TL;DR
- Drizzle: Recommended default untuk new project. TypeScript-first, edge-compatible, lightweight.
- Prisma: Recommended kalau team familiar atau butuh introspect existing database.
- Kysely: Recommended kalau Anda prefer SQL-like syntax dengan TypeScript type safety.
Konteks
5 project saya 2024-2026:
- 3 pakai Drizzle (semua baru)
- 1 pakai Prisma (legacy, sudah ada di project)
- 1 pakai Kysely (eksperimen, lalu migrate ke Drizzle)
Drizzle
Apa itu
TypeScript-first ORM/query builder. Lightweight (no codegen, no extra binary).
Schema definition
// db/schema.ts
import { pgTable, text, integer, timestamp, boolean } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: text('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name').notNull(),
role: text('role', { enum: ['admin', 'user'] }).default('user').notNull(),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
export const posts = pgTable('posts', {
id: text('id').primaryKey(),
userId: text('user_id').notNull().references(() => users.id),
title: text('title').notNull(),
published: boolean('published').default(false).notNull(),
});
Query example
import { eq, and } from 'drizzle-orm';
// Simple select
const user = await db.select().from(users).where(eq(users.email, '[email protected]'));
// Join
const userWithPosts = await db.select()
.from(users)
.leftJoin(posts, eq(posts.userId, users.id))
.where(eq(users.id, 'user_123'));
// Insert + return
const inserted = await db.insert(users)
.values({ id: 'u1', email: '[email protected]', name: 'Asti' })
.returning();
Pro
- TypeScript type inference excellent
- Edge-compatible (work di Cloudflare Workers, Vercel Edge)
- Minimal runtime overhead
- Migration tool built-in (
drizzle-kit) - Drizzle-zod integration: schema → Zod schema otomatis
Con
- Less mature dari Prisma (smaller ecosystem)
- Relational query pattern lebih verbose dari Prisma
- Documentation OK tapi tidak as polished
- Community lebih kecil
Prisma
Apa itu
Mature ORM dengan codegen + schema-first approach.
Schema definition
// prisma/schema.prisma
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
role String @default("user")
posts Post[]
createdAt DateTime @default(now())
}
model Post {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
title String
published Boolean @default(false)
}
Lalu run prisma generate untuk gen client.
Query example
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Simple select
const user = await prisma.user.findUnique({ where: { email: '[email protected]' } });
// Include relation
const userWithPosts = await prisma.user.findUnique({
where: { id: 'user_123' },
include: { posts: true },
});
// Create
const created = await prisma.user.create({
data: { email: '[email protected]', name: 'Asti' },
});
Pro
- Most mature TS ORM (dominant since 2020)
- Schema-first: source of truth jelas di
schema.prisma - Relational query API ergonomic (
include,select) - Excellent docs + community
- Prisma Studio: visual DB browser (gratis, helpful)
- Introspect existing database
Con
- Codegen step: setiap schema change, butuh
prisma generate. Lupa = type out of sync. - Heavy runtime: bundle size ~10MB, query engine binary additional
- Edge issue: tidak fully work di Cloudflare Workers (butuh Driver Adapter, masih beta)
- Migration tool kompleks: lebih powerful dari Drizzle Kit tapi steep learning curve
Kysely
Apa itu
Type-safe SQL query builder. Tidak ada ORM abstraction — Anda write SQL-like syntax dengan TypeScript types.
Schema definition
// db/types.ts
export interface Database {
users: UsersTable;
posts: PostsTable;
}
export interface UsersTable {
id: string;
email: string;
name: string;
role: 'admin' | 'user';
created_at: Date;
}
export interface PostsTable {
id: string;
user_id: string;
title: string;
published: boolean;
}
Query example
import { Kysely, PostgresDialect } from 'kysely';
const db = new Kysely<Database>({ dialect: new PostgresDialect({ ... }) });
// Simple select
const user = await db.selectFrom('users')
.selectAll()
.where('email', '=', '[email protected]')
.executeTakeFirst();
// Join
const userWithPosts = await db.selectFrom('users')
.leftJoin('posts', 'posts.user_id', 'users.id')
.selectAll()
.where('users.id', '=', 'user_123')
.execute();
Pro
- SQL-like syntax (familiar untuk SQL dev)
- Type safety excellent (compile-time check)
- No codegen
- Lightweight (similar to Drizzle)
- Multi-DB support (Postgres, MySQL, SQLite)
Con
- Tidak ada ORM abstraction (no
findUnique({ include: ... })pattern) - Migration tool external (Kysely-migrator, less integrated)
- Smaller community than Drizzle/Prisma
- Less type inference power for complex query
Performance
Bundle size
| ORM | Bundle (gzipped) |
|---|---|
| Drizzle | ~30 KB |
| Kysely | ~25 KB |
| Prisma | ~250 KB + binary |
Drizzle/Kysely jauh lebih kecil. Untuk edge function (CF Workers 1MB limit), Prisma struggle.
Query speed
Sama query (select user by email, simple index):
| ORM | Avg latency (Postgres local) |
|---|---|
| Raw pg | 0.8ms |
| Kysely | 0.9ms |
| Drizzle | 1.0ms |
| Prisma | 2.5ms |
Prisma 2-3x slower due to query engine overhead. Drizzle/Kysely close to raw.
Edge compatibility
| ORM | Cloudflare Workers | Vercel Edge | Bun |
|---|---|---|---|
| Drizzle | ✅ Native | ✅ Native | ✅ Native |
| Prisma | ⚠️ Driver Adapter (beta) | ⚠️ Driver Adapter | ✅ Native |
| Kysely | ✅ Native | ✅ Native | ✅ Native |
Untuk edge-first stack, Drizzle atau Kysely safer.
Schema migration
Drizzle Kit
bunx drizzle-kit generate # generate SQL migration from schema diff
bunx drizzle-kit migrate # apply migration
bunx drizzle-kit studio # web UI to browse DB
Migration file SQL. Manual edit OK. Simple.
Prisma Migrate
bunx prisma migrate dev --name add_user_role
bunx prisma migrate deploy # production
bunx prisma studio # web UI
More powerful (shadow database, drift detection) tapi more complex. Bagus untuk team yang butuh strict migration workflow.
Kysely
External tool: kysely-codegen (gen types from DB) + manual SQL migration file. Less integrated, more manual.
Use case decision
| Use case | Recommended |
|---|---|
| New project, Bun + Hono + Postgres/SQLite | Drizzle |
| New project, edge-first (CF Workers) | Drizzle atau Kysely |
| Team familiar with Prisma | Prisma (stay) |
| Existing database, butuh introspect | Prisma (introspect feature) |
| SQL purist, prefer raw control | Kysely |
| Bundle size critical | Drizzle atau Kysely |
| Need maximum type inference | Drizzle (slight edge over Prisma di 2026) |
Konteks Indonesia
Untuk SMB Indonesia 2026:
- Project new + edge-first: Drizzle default safe
- Project legacy yang sudah Prisma: stay (migration cost > benefit)
- Tim SQL-senior yang prefer query builder: Kysely
Migration paths
Prisma → Drizzle
Effort: 4-8 jam untuk 10-20 table schema.
- Convert
schema.prismake Drizzle schema - Migrate Prisma migrate history (atau start fresh)
- Refactor query (most API similar enough)
Kysely → Drizzle (atau sebaliknya)
Effort: 2-4 jam.
- Both lightweight, syntax similar
- Schema definition different tapi mechanical conversion
Drizzle → Prisma
Effort: 6-12 jam.
- Convert schema definition (Drizzle TS → Prisma .prisma)
- Add codegen step ke build
- Update query syntax
Yang surprising
Drizzle’s relational query API ($\sim$2024) initially feel less ergonomic dari Prisma’s include. Tapi setelah pakai 6 bulan, saya prefer Drizzle karena type inference lebih predictable.
Prisma’s “magic” sometimes obscure what SQL actually runs. Untuk debug complex query, Drizzle’s explicit query lebih clear.
Verdict
Recommended:
- Drizzle untuk new project SMB Indonesia di 2026 (default)
- Prisma untuk existing project + team yang sudah familiar
- Kysely untuk SQL purist atau project SQL-heavy
Hindari:
- Prisma di Cloudflare Workers (sampai Driver Adapter fully stable)
- Raw SQL string concat untuk dynamic query (gunakan query builder)
Ditulis oleh Asti Larasati