← Back to articles

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

DrizzlePrismaTypeORM
PhilosophySQL in TypeScriptAbstract SQL awayDecorator-based entities
Query styleSQL-like builderMethod chainsRepository pattern
TypesInferred from schemaGenerated from schemaManual + decorators
Bundle~35KB~2MB~500KB
Build stepNoneprisma generateNone
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.

Get AI tool guides in your inbox

Weekly deep-dives on the best AI coding tools, automation platforms, and productivity software.