Drizzle ORM Review (2026)
Drizzle ORM is a TypeScript ORM that feels like writing SQL. No query engine, no code generation, no binary dependencies — just typed SQL queries that compile to exactly the SQL you'd write by hand. The fastest, lightest ORM in the TypeScript ecosystem.
What Makes Drizzle Different
| Drizzle | Prisma | TypeORM | |
|---|---|---|---|
| Philosophy | SQL in TypeScript | Abstract SQL away | Decorator-based entities |
| Query style | SQL-like builder | Method chains | Repository pattern |
| Types | Inferred from schema | Generated from schema | Manual + decorators |
| Bundle | ~35KB | ~2MB | ~500KB |
| Build step | None | prisma generate | None |
| Edge support | ✅ Native | ⚠️ Improving | ❌ |
Schema Definition
import { pgTable, serial, text, integer, timestamp, boolean } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
age: integer('age'),
active: boolean('active').default(true),
createdAt: timestamp('created_at').defaultNow(),
});
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id),
publishedAt: timestamp('published_at'),
});
Your schema is TypeScript. Types are inferred automatically. Change a column → TypeScript errors everywhere that column is used.
Query Examples
Select
// Simple
const allUsers = await db.select().from(users);
// With conditions
const activeUsers = await db
.select()
.from(users)
.where(and(eq(users.active, true), gt(users.age, 18)));
// Specific columns
const names = await db
.select({ name: users.name, email: users.email })
.from(users);
Join
const usersWithPosts = await db
.select({
userName: users.name,
postTitle: posts.title,
})
.from(users)
.leftJoin(posts, eq(users.id, posts.authorId))
.where(isNotNull(posts.publishedAt));
Insert
await db.insert(users).values({
name: 'John',
email: 'john@example.com',
age: 30,
});
// Bulk insert
await db.insert(users).values([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
]);
// Insert returning
const [newUser] = await db.insert(users)
.values({ name: 'John', email: 'john@example.com' })
.returning();
Update & Delete
await db.update(users)
.set({ active: false })
.where(lt(users.createdAt, new Date('2025-01-01')));
await db.delete(users)
.where(eq(users.id, 123));
Relations (Query API)
import { relations } from 'drizzle-orm';
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));
// Query with relations (Prisma-like syntax)
const usersWithPosts = await db.query.users.findMany({
with: { posts: true },
where: eq(users.active, true),
});
What's Great
If You Know SQL, You Know Drizzle
Every Drizzle query maps directly to SQL. No ORM-specific mental model to learn. select().from().where().leftJoin() is exactly how you'd think about the SQL query.
Debugging is trivial: Log the generated SQL. It's the exact query you'd write manually. No hidden N+1 queries. No unexpected JOINs. No "what SQL is my ORM generating?"
Performance
No query engine between your code and the database. Drizzle generates a SQL string and passes it to your database driver. The overhead is essentially zero.
Benchmarks consistently show Drizzle as 2-5x faster than Prisma for common operations, and comparable to raw SQL queries.
Edge & Serverless Native
35KB bundle. No binary dependencies. Works everywhere:
- ✅ Cloudflare Workers (D1, Hyperdrive)
- ✅ Vercel Edge Functions
- ✅ Deno Deploy
- ✅ Bun
- ✅ Node.js
- ✅ AWS Lambda
Prisma's ~2MB query engine is a non-starter for many edge environments. Drizzle has no such limitation.
No Code Generation
Schema changes → types update automatically (TypeScript inference). No prisma generate step. No generated client to commit or gitignore. One less build step.
Database Support
// PostgreSQL
import { drizzle } from 'drizzle-orm/node-postgres';
// MySQL
import { drizzle } from 'drizzle-orm/mysql2';
// SQLite
import { drizzle } from 'drizzle-orm/better-sqlite3';
// Neon (serverless PG)
import { drizzle } from 'drizzle-orm/neon-http';
// PlanetScale (serverless MySQL)
import { drizzle } from 'drizzle-orm/planetscale-serverless';
// Cloudflare D1
import { drizzle } from 'drizzle-orm/d1';
// Turso (libSQL)
import { drizzle } from 'drizzle-orm/libsql';
Migrations with drizzle-kit
# Generate migration from schema changes
npx drizzle-kit generate
# Apply migrations
npx drizzle-kit migrate
# Visual database browser
npx drizzle-kit studio
drizzle-kit studio opens a browser-based database viewer — Drizzle's answer to Prisma Studio.
Where It Falls Short
SQL Knowledge Required
Drizzle assumes you understand SQL. JOINs, subqueries, aggregations — you need to know these concepts. Prisma abstracts SQL away; Drizzle embraces it.
For SQL beginners: Prisma is a better starting point. Learn SQL alongside Prisma, then switch to Drizzle when you want more control.
Smaller Ecosystem
Fewer tutorials, fewer community plugins, fewer Stack Overflow answers than Prisma. The documentation is good but not as comprehensive. You're more likely to read source code for advanced use cases.
Relations API is Less Intuitive
The Query API (.query.users.findMany({ with: { posts: true } })) works but feels bolted on. Drizzle's strength is the SQL-like builder. If you prefer Prisma's relation-style queries, Drizzle's Query API is functional but less polished.
Migration Tooling
drizzle-kit generates migrations and applies them. It works well for standard cases. But Prisma Migrate handles more complex scenarios (data migrations, custom SQL in migrations) more gracefully.
Fewer Escape Hatches for Complex Queries
Drizzle handles most SQL well, but some complex queries (recursive CTEs, complex window functions) may require raw SQL. The sql template tag handles this, but it's less type-safe than the builder API.
Pricing
Free. Open source (Apache 2.0). No paid tier, no usage limits, no vendor dependency.
FAQ
Should I switch from Prisma to Drizzle?
If you're happy with Prisma and don't need edge support or better performance: stay on Prisma. If you're frustrated with Prisma's bundle size, build step, or performance: Drizzle is the upgrade.
Is Drizzle production-ready?
Yes. Stable API, active development, and used in production by many companies. The 1.0 release solidified the API surface.
Can I use Drizzle with Next.js?
Yes. Works with Next.js App Router, Server Components, API Routes, and Server Actions. Pairs well with Neon, PlanetScale, or Turso for serverless.
How do I handle database seeding?
Write seed scripts as regular TypeScript files using Drizzle's insert API. Run with tsx seed.ts. No special seeding framework needed.
Does Drizzle support transactions?
Yes. db.transaction(async (tx) => { ... }) with full type safety inside the transaction block.
Bottom Line
Drizzle ORM is the best TypeScript ORM for developers who know SQL and want type safety without abstraction overhead. Zero bundle size concerns, edge-native, and the fastest runtime performance of any TypeScript ORM.
Start with: Install drizzle-orm + your database driver. Define your schema. Run drizzle-kit generate for migrations. Write queries. If you know SQL, you'll be productive in 30 minutes.