back

Why I Switched to Drizzle ORM — And What I Wish I Knew Earlier

October 3, 2025·7 min read·Antima Singh

Before Drizzle, I used Prisma. Prisma is excellent, but its query engine binary, opaque migrations, and JS-centric philosophy started to feel like friction once I wanted to lean into SQL properly. Drizzle is different — it is thin, TypeScript-native, and SQL-first.

The schema is the source of truth

In Drizzle, you define your tables in TypeScript. The schema is the single source of truth — from it, TypeScript types, SQL migrations, and the query builder are all derived. This eliminates the "schema drift" problem where your Prisma schema and your actual database diverge silently.

export const projects = pgTable('projects', {
  id: serial('id').primaryKey(),
  title: varchar('title', { length: 255 }).notNull(),
  slug: varchar('slug', { length: 255 }).notNull().unique(),
  published: boolean('published').default(false).notNull(),
  createdAt: timestamp('created_at').defaultNow().notNull(),
});

export type Project = typeof projects.$inferSelect;

Queries feel like SQL

Drizzle queries are just TypeScript. They compile to SQL you can inspect. No magic. If you know SQL, you know how to write a Drizzle query.

const published = await db
  .select()
  .from(projects)
  .where(eq(projects.published, true))
  .orderBy(desc(projects.createdAt));

Migrations are plain SQL files

Run `drizzle-kit generate` and you get a SQL migration file you can read, edit, and commit to version control. No black-box engine. I have never had a surprise in production.

What to watch out for

Drizzle is younger than Prisma. The documentation has gaps, and some advanced patterns (complex joins, CTEs) require more manual work than Prisma's fluent API. For greenfield projects, though, it is my default choice every time.