A developer said: 'Prisma generates 10MB of client code and adds 100ms to cold starts. Drizzle generates zero — it's just TypeScript functions that map to SQL. Same type safety, zero overhead.'
What Drizzle ORM Offers
Drizzle (open source, free):
- Zero runtime overhead — no code generation, no engine
- SQL-like syntax — if you know SQL, you know Drizzle
- Full type safety — inferred types from your schema
- Any database — PostgreSQL, MySQL, SQLite, Turso, Neon, PlanetScale
- Drizzle Kit — migrations, push, studio
- Edge-ready — works everywhere (Cloudflare, Vercel, Bun)
- Serverless-friendly — sub-10ms cold starts
Quick Start
npm install drizzle-orm postgres
npm install -D drizzle-kit
Define Schema
// src/db/schema.ts
import { pgTable, text, boolean, timestamp, integer, uuid } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
role: text('role', { enum: ['user', 'admin'] }).default('user'),
createdAt: timestamp('created_at').defaultNow()
});
export const posts = pgTable('posts', {
id: uuid('id').primaryKey().defaultRandom(),
title: text('title').notNull(),
content: text('content'),
published: boolean('published').default(false),
authorId: uuid('author_id').references(() => users.id),
views: integer('views').default(0),
createdAt: timestamp('created_at').defaultNow()
});
Queries (SQL-Like Syntax)
import { drizzle } from 'drizzle-orm/postgres-js';
import { eq, gt, desc, and, sql, count, avg } from 'drizzle-orm';
import postgres from 'postgres';
import * as schema from './schema';
const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });
// Select with filter
const publishedPosts = await db
.select()
.from(schema.posts)
.where(eq(schema.posts.published, true))
.orderBy(desc(schema.posts.createdAt))
.limit(10);
// Join
const postsWithAuthor = await db
.select({
title: schema.posts.title,
authorName: schema.users.name,
authorEmail: schema.users.email
})
.from(schema.posts)
.leftJoin(schema.users, eq(schema.posts.authorId, schema.users.id))
.where(eq(schema.posts.published, true));
// Insert
const newPost = await db
.insert(schema.posts)
.values({ title: 'Hello Drizzle', authorId: userId })
.returning();
// Update
await db
.update(schema.posts)
.set({ published: true, views: sql`${schema.posts.views} + 1` })
.where(eq(schema.posts.id, postId));
// Delete
await db.delete(schema.posts).where(eq(schema.posts.id, postId));
// Aggregate
const stats = await db
.select({
authorId: schema.posts.authorId,
postCount: count(),
avgViews: avg(schema.posts.views)
})
.from(schema.posts)
.groupBy(schema.posts.authorId);
Relations (Query API)
// Define relations
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
const usersWithPosts = await db.query.users.findMany({
with: { posts: { where: eq(posts.published, true) } },
limit: 10
});
Migrations
# Generate migration
npx drizzle-kit generate
# Apply migration
npx drizzle-kit migrate
# Push schema directly (dev)
npx drizzle-kit push
# Visual database browser
npx drizzle-kit studio
Drizzle vs Prisma
| Drizzle | Prisma |
|---|---|
| Zero codegen | 10MB+ generated client |
| SQL-like syntax | Custom query API |
| Sub-10ms cold start | 100ms+ cold start |
| ~30KB bundle | ~600KB bundle |
| Edge-native | Needs Accelerate for edge |
| No engine | Requires query engine |
Need data for your database? Check out my web scraping actors on Apify.
Need help with database architecture? Email me at spinov001@gmail.com.
Top comments (0)