What Is Drizzle ORM? TypeScript SQL Builder

Photo: Vladimir Srajber / Pexels
Drizzle ORM is a lightweight, fully type-safe object-relational mapper (ORM — a layer that lets application code read and write database rows as typed objects instead of raw SQL strings) built for TypeScript. It was created by developer Andrii Sherman and released publicly in 2022 under the tagline "if you know SQL, you know Drizzle." That line describes the entire design philosophy: queries read almost exactly like SQL, the database schema is declared as plain TypeScript, and there is no hidden runtime engine translating your code into queries behind the scenes. Drizzle runs on Node.js, Bun, Deno, and Cloudflare Workers, and by 2026 it has become the most common alternative developers reach for when Prisma feels too heavy for a serverless or edge-first project.
The problem Drizzle was built to solve
Most traditional ORMs — Hibernate for Java, Active Record for Ruby, and Prisma for TypeScript — hide SQL behind a domain-specific language (DSL). You write user.posts.find() and the ORM translates that into a query somewhere you can't see. This is convenient for beginners but creates two recurring problems for production teams: unpredictable query generation (the classic "N+1 query" bug, where a loop silently fires one database round-trip per item instead of one batched query) and heavyweight runtimes that hurt cold-start latency.
Cold start matters more than it used to. Serverless functions and edge workers (code that runs on servers physically close to the user, at providers like Cloudflare, instead of one central data center) spin up fresh instances constantly, and every extra megabyte of dependency code and every extra database-driver handshake adds milliseconds before the function can even begin answering the request. According to a widely cited comparison from Encore, a backend infrastructure company, Drizzle's client ships at roughly 7.4 KB gzipped with cold starts around 45 milliseconds, while Prisma's older binary-engine architecture (Prisma 6) carried cold starts closer to 1,200 milliseconds in serverless environments before the newer engine-free Prisma 7 runtime cut that down to roughly 320 milliseconds (Encore, "Drizzle vs Prisma in 2026"). Drizzle's answer to both problems is architectural: don't generate a runtime engine at all, and don't invent a new query language. Write something that looks like SQL, type-check it at compile time, and execute it directly against the driver.
How Drizzle's type system actually works
Think of Drizzle's schema file as a blueprint that does double duty. In most ORMs, the blueprint (schema) and the finished tool (typed query client) are separate artifacts — you write a schema, then run a code generator, then import the generated client. Drizzle collapses that into one file: the same TypeScript object you use to define a table (pgTable("users", {...})) is the exact object you import to query that table. There's no intermediate generation step at build time.
That single design choice is why Drizzle needs no code generator and why its bundle stays small: TypeScript's own compiler infers the shape of every query result directly from the schema object, the same way it infers the return type of any ordinary function. Compare this to Prisma, which reads a separate .prisma DSL file, runs prisma generate, and writes out a compiled @prisma/client package (commonly several megabytes with its query engine binary) that your application then imports.
What is a schema-as-code ORM?
A schema-as-code ORM defines database tables using the host programming language itself (TypeScript, in Drizzle's case) rather than a separate schema definition language. The table definition is both the design document and the runtime object the application queries against, so there is nothing to regenerate when the schema changes — only a migration to write and apply.
Schema definition in practice
Here is a two-table schema with a foreign key relationship, written the way a real Postgres-backed Drizzle project would define it:
import { pgTable, serial, text, timestamp, integer } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
export const users = pgTable("users", {
id: serial("id").primaryKey(),
email: text("email").notNull().unique(),
createdAt: timestamp("created_at").defaultNow(),
});
export const posts = pgTable("posts", {
id: serial("id").primaryKey(),
authorId: integer("author_id").references(() => users.id),
title: text("title").notNull(),
body: text("body"),
});
export const userRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
Every field here is a plain TypeScript const. There's no .prisma file, no YAML, no XML mapping document — just objects the compiler already understands. typeof users.$inferSelect gives you the exact row type Postgres will return for a SELECT * FROM users, and it updates automatically the moment you add or rename a column, with zero regeneration step.
Querying: two styles, one mental model
Drizzle offers two ways to write queries, and understanding when to reach for each one is the most practical skill for a new Drizzle developer.
The SQL-like query builder
This is the lower-level, closer-to-SQL API. If you can picture the SELECT ... FROM ... WHERE ... clause in your head, you can write it here almost verbatim:
import { eq } from "drizzle-orm";
import { db } from "./db";
import { users } from "./schema";
const result = await db
.select({ id: users.id, email: users.email })
.from(users)
.where(eq(users.email, "ada@example.com"))
.limit(1);
// result: { id: number; email: string }[]
Every clause maps one-to-one to the SQL Postgres will actually execute. There is no hidden query planning happening behind the .select() call — what you write is what runs, which is precisely the guarantee that eliminates surprise N+1 queries.
The relational query API
For nested data — a user with their posts, a post with its comments and author — Drizzle offers a more ergonomic relational API that still returns fully typed results:
const user = await db.query.users.findFirst({
where: (u, { eq }) => eq(u.email, "ada@example.com"),
with: { posts: true },
});
// user.posts is fully typed as posts[]
Under the hood, this still compiles down to a small number of SQL statements (typically one query with a lateral join or a couple of batched queries), not one query per row — the exact N+1 pattern Drizzle was designed to avoid.
Transactions
Multi-statement operations that must all succeed or all fail together use the same db object, wrapped in a transaction callback:
await db.transaction(async (tx) => {
const [u] = await tx.insert(users).values({ email: "x@y.com" }).returning();
await tx.insert(posts).values({ authorId: u.id, title: "Hello" });
});
If the second insert throws, Postgres rolls back the first insert automatically. This is standard relational database behavior — Drizzle just gives you a typed handle (tx) to work with inside the block.
The raw SQL escape hatch
For anything the query builder can't express cleanly — window functions, complex aggregations, database-specific extensions — Drizzle lets you drop to raw SQL without leaving the type system:
import { sql } from "drizzle-orm";
const rows = await db.execute(sql`
SELECT date_trunc('day', created_at) AS day, count(*)
FROM users
GROUP BY 1 ORDER BY 1 DESC
`);
This matters more than it looks. Query builders that don't offer a real escape hatch eventually force developers into awkward workarounds for anything the DSL wasn't designed to handle. Drizzle's philosophy is the opposite of hiding SQL: raw SQL is always one import away, and it's parameterized automatically to prevent SQL injection.
Migrations with drizzle-kit
drizzle-kit is Drizzle's companion command-line tool, responsible for turning schema changes into actual database migrations:
# generate SQL migration from schema diff
npx drizzle-kit generate
# apply migrations
npx drizzle-kit migrate
# open Drizzle Studio (local GUI)
npx drizzle-kit studio
Generated migrations are ordinary .sql files checked into version control — nothing proprietary, easy to review line-by-line in a pull request, and portable to any tool that can run SQL. For local development, drizzle-kit push syncs the database directly to match the current schema without generating a migration file at all, which mirrors the fast dev-loop feel of Prisma's db push. Drizzle Studio is a free, browser-based GUI for inspecting and editing table data during development, comparable to Prisma Studio.
As of early 2026, drizzle-kit is undergoing an internal rewrite ahead of the stable v1.0 release. Drizzle's own release notes describe reduced schema-introspection time (cut from roughly ten seconds down to under one second by minimizing round-trip database calls) and expanded automated test coverage across migration scenarios like push-then-push and pull-then-generate sequences, alongside new first-class support for Microsoft SQL Server in drizzle-orm, drizzle-kit, and drizzle-seed (Drizzle ORM, Latest Releases documentation).
Supported databases and drivers
| Database | Common drivers | Best-known hosting fit |
|---|---|---|
| PostgreSQL | node-postgres, postgres.js, Neon serverless driver | Neon, Vercel Postgres, Supabase, AWS RDS, Aurora |
| MySQL | mysql2, PlanetScale serverless driver | PlanetScale, AWS RDS |
| SQLite | better-sqlite3, libSQL, bun:sqlite, D1 | Turso (libSQL), Cloudflare D1, Bun, Expo apps |
| Microsoft SQL Server | mssql (new in 2026 releases) | Azure SQL, on-prem MSSQL |
| SingleStore | SingleStore driver | SingleStore Cloud |
Table: Databases and drivers officially supported by Drizzle ORM as of mid-2026.
The Turso (libSQL) and Cloudflare D1 combination is why Drizzle shows up disproportionately often in edge-native stacks: both are SQLite-compatible, both are designed to run close to the request at the network edge, and Drizzle's SQLite dialect maps to both with almost no code changes.
Why edge and serverless teams reach for Drizzle
The single biggest reason teams pick Drizzle over a heavier ORM is deployment target. Think of it like packing for a trip: Prisma is a full suitcase with everything you might need already organized inside — a generated client, a query engine, a migration history table, built-in connection pooling extras. Drizzle is a daypack: lighter, faster to grab, but you sometimes have to carry a few things yourself that the suitcase would have packed for you.
That daypack model pays off specifically in environments billed by execution time and memory, where every millisecond of cold start is a cost line item, not just a UX annoyance. Cloudflare Workers, Vercel Edge Functions, and Deno Deploy all impose strict bundle-size and startup-time constraints that historically excluded engine-based ORMs entirely — Prisma's binary query engine simply could not run in some of these environments before Prisma introduced driver adapters and, later, a fully rewritten Rust-free engine in Prisma 7.
Drizzle vs Prisma vs Kysely vs TypeORM
| Feature | Drizzle | Prisma | Kysely | TypeORM |
|---|---|---|---|---|
| Schema language | TypeScript objects | .prisma DSL file |
TypeScript interfaces | TypeScript decorators |
| Query style | SQL-like + relational API | High-level method DSL | Pure query builder | DSL + Active Record |
| Type safety | Full compiler inference | Full (generated client) | Full compiler inference | Partial (decorator-based) |
| Client bundle size | ~7.4 KB gzipped | ~1.6 MB (Prisma 7, down from a multi-MB engine binary in Prisma 6) | ~15 KB | Medium, no lean mode |
| Cold start (serverless) | ~45 ms | ~320 ms (Prisma 7); ~1,200 ms (Prisma 6 binary engine) | Fast, no engine | Slower, reflection-heavy |
| Edge runtime support | First-class (D1, Neon, Turso adapters) | Improving via driver adapters | First-class | Limited |
| Migrations | drizzle-kit, plain .sql files |
prisma migrate, SQL + metadata | None built-in (pair with a separate migrator) | Built-in, decorator-driven |
| Studio GUI | Drizzle Studio (free) | Prisma Studio (free) | None | None |
| First released | 2022 | 2019 | 2021 | 2016 |
| Type-check speed on large schemas | Slower (compiler infers live) | Faster (pre-generated types) | Comparable to Drizzle | N/A (decorators, not inference) |
Table: Feature comparison of the four most common TypeScript-first ORMs and query builders as of mid-2026, based on Encore's 2026 comparison and Prisma's September 2025 type-checking benchmark.
Where each tool actually wins
Concrete scenarios matter more than abstract feature lists here, so consider four real situations.
A Cloudflare Workers API with a D1 database. Drizzle wins clearly. D1 is SQLite-based and edge-native by design; Drizzle's SQLite dialect and D1 driver were built for exactly this pairing, and the small bundle size keeps the Worker under Cloudflare's size limits comfortably.
A large internal enterprise tool with a five-person backend team that values guardrails. Prisma tends to win here. Its generated client catches schema drift at build time in a very visible way, Prisma Studio is a mature data-browsing tool, and features like Prisma Accelerate (a managed connection-pooling and caching layer) reduce operational burden for teams without dedicated database infrastructure engineers.
A startup building a Next.js App Router product that needs to move fast and deploy to Vercel's edge runtime for some routes and Node runtime for others. Drizzle again tends to win, mostly because it works identically in both runtimes without driver-adapter configuration differences, and the SQL-like syntax means SQL-literate engineers can read query logic without learning a new DSL.
A team migrating a fifteen-year-old Java-influenced codebase that already relies on Active Record–style patterns and decorators. TypeORM remains a reasonable choice here purely for migration continuity — it's the closest TypeScript equivalent to the Active Record pattern those developers already know, even though it lags in Edge support and active development pace compared to Drizzle and Prisma.
Where Drizzle loses
Honesty matters more than advocacy here. Drizzle is not the right choice in a few recurring situations.
- You depend on Prisma's managed ecosystem. Prisma Accelerate (connection pooling plus query caching) and Prisma Pulse (real-time change-data-capture events) have no direct Drizzle equivalent; you'd need to assemble similar functionality yourself from separate tools like PgBouncer and Postgres logical replication.
- Your team actively wants an abstraction layer over SQL. Some teams prefer not knowing SQL at all and want the ORM's DSL to hide it entirely — that's a legitimate preference, and Prisma's method-chaining API caters to it more directly than Drizzle's SQL-mirroring style.
- You need auto-generated REST or GraphQL scaffolding from your schema. Prisma's ecosystem has more mature third-party tooling for this (for example, community GraphQL-generator packages built against Prisma's generated client types).
- You're on MongoDB or another document database. Drizzle is SQL-relational only; it has no MongoDB dialect, unlike Prisma or Mongoose.
- Your team's TypeScript compile times are already a pain point. Given Prisma's September 2025 benchmark advantage in type-check speed, adding Drizzle's live schema inference to an already-large monorepo can measurably slow down
tscand editor responsiveness, especially on schemas with dozens of tables.
Performance in the real world
Per-query overhead for both Drizzle and Prisma is small in absolute terms — typically a few milliseconds for parameter binding and result-row mapping, dwarfed by network round-trip time to the database itself. The performance conversation that actually matters in production is almost entirely about two other things: cold-start latency and type-check time during development, not raw query execution speed.
On raw query execution, independent benchmarking summarized by TheDataGuy in December 2025 found the gap between ORMs largely closes once you're running complex joins and aggregations against a real database — TypeORM using raw SQL clocked around 45 milliseconds, Prisma around 43 milliseconds, and Drizzle around 41 milliseconds for comparable multi-table queries, differences small enough to be noise relative to network latency (TheDataGuy, "Node.js ORMs in 2025," December 2025). The meaningful performance story is upstream of query execution: it's about how fast your function can start responding at all (cold start) and how fast your team's editor and CI can type-check the codebase (compile time), and those two metrics point in opposite directions for Drizzle versus Prisma — Drizzle wins cold start decisively, Prisma wins type-check speed decisively.
Common patterns in production Drizzle codebases
- Schema in a shared monorepo package. Teams colocate table definitions and inferred types in one internal package (
@company/db-schema) consumed by both the API server and background workers, so a column rename only needs to happen in one place. - Zod inference via
drizzle-zod. This companion package derives Zod validation schemas directly from Drizzle table definitions, so request-body validation and database column constraints stay in sync without maintaining two parallel type definitions. - Composable query helpers for soft deletes and multi-tenancy. Because there's no plugin system to fight, teams write small functions that wrap
.where()clauses (for example, always appendingeq(table.deletedAt, null)) rather than reaching for an ORM-specific soft-delete plugin. - Read replicas for scaling reads. Drizzle supports routing SELECT queries to replica connections separately from writes, a pattern common once a Postgres instance starts hitting read-throughput limits.
What people get wrong about Drizzle
A few misconceptions come up often enough to be worth addressing directly.
"Drizzle has no migrations, so it's not production-safe." This is false. Drizzle absolutely supports versioned SQL migrations through drizzle-kit generate and drizzle-kit migrate; the confusion usually comes from drizzle-kit push, which is a separate dev-only command that syncs schema without generating a migration file, similar to Prisma's db push.
"Drizzle is basically the same as Kysely." They're closely related in philosophy (both are SQL-like, both avoid code generation) but Drizzle adds schema definition, a relational query API, and first-party migration tooling, while Kysely is deliberately scoped to just the query builder and expects you to pair it with a separate migration tool.
"Smaller bundle size always means faster in production." Bundle size mainly affects cold start, not steady-state query latency once a serverless function or long-running server process is already warm. For a traditional Node.js server that stays running between requests, Prisma's larger bundle has effectively no per-request cost — the cold-start advantage only matters if your function actually cold-starts often.
"Drizzle can't do what Prisma does with relations." Drizzle's relational query API (db.query.users.findFirst({ with: { posts: true } })) supports nested reads across multiple relation levels, similar to Prisma's include. The syntax differs, but the capability gap is narrower than developers coming from Prisma sometimes assume.
Frequently asked questions
Q: Is Drizzle ORM production-ready in 2026? A: Yes. Drizzle has been used in production since well before 2026, and by mid-2026 its companion CLI, drizzle-kit, is in beta toward a stable v1.0 release with expanded test coverage and new MSSQL support, according to Drizzle's own release documentation.
Q: Drizzle vs Prisma — which should I pick for a new project? A: For edge or serverless deployments (Cloudflare Workers, Vercel Edge Functions, Deno Deploy), Drizzle's smaller bundle and faster cold start make it the stronger default. For a traditional Node.js monolith where a team values Prisma's generated client, Prisma Studio, and managed add-ons like Accelerate, Prisma remains an excellent, well-supported choice. Both are actively maintained and the practical gap for most teams is smaller than online debates suggest.
Q: Does Drizzle generate code like Prisma does?
A: Only migration SQL files, via drizzle-kit generate. There is no runtime client generator step — the TypeScript schema file you write is the same object your application queries against, and types are inferred by the compiler rather than pre-generated.
Q: Can I write raw SQL in Drizzle?
A: Yes. The sql tagged template lets you write parameterized raw SQL directly, and you can mix raw SQL fragments into otherwise typed Drizzle queries for anything the query builder doesn't express cleanly, like window functions.
Q: Does Drizzle support database migrations?
A: Yes, through drizzle-kit. generate creates SQL migration files from schema diffs, migrate applies them, and push syncs a dev database directly without generating a file, similar to Prisma's db push command.
Q: Is Drizzle good for Cloudflare Workers and D1? A: This is arguably Drizzle's strongest niche. It has first-class driver support for Cloudflare D1, Hyperdrive, Neon's serverless driver, and Turso's libSQL, all of which are common choices for edge-deployed applications.
Q: Why is Drizzle's TypeScript compile time slower than Prisma's in some benchmarks? A: Because Drizzle infers query result types live from the schema object at compile time, while Prisma pre-generates a fully typed client ahead of time. Prisma's September 2025 benchmark measured this gap directly: roughly twice as fast type-checking for Prisma on comparable relational queries.
Q: Does Drizzle work with frameworks like Next.js, Astro, and SvelteKit? A: Yes. Drizzle has no framework dependency — it's a database library, not a web framework — so it works the same way inside a Next.js API route, an Astro server endpoint, or a SvelteKit server load function, as long as the driver you choose matches your deployment target.
Q: Is Drizzle free and open source? A: Yes. Drizzle ORM, drizzle-kit, and Drizzle Studio are all released under the Apache 2.0 license and hosted publicly on GitHub, with no paid tier required to use the core library.
Q: What database types does Drizzle NOT support? A: Drizzle is relational-database-only. It has no MongoDB or other document-database dialect. As of 2026 it covers PostgreSQL, MySQL, SQLite (including libSQL/Turso and Cloudflare D1), SingleStore, and newly added Microsoft SQL Server support.
The takeaway
Drizzle ORM's core bet is that developers who already know SQL don't need it hidden from them, they need it typed. That bet has paid off specifically in edge and serverless environments, where its tiny bundle and fast cold start solve a real operational cost that Prisma's engine-based architecture struggled with for years. The trade-off is real too: Prisma's pre-generated client checks types faster and ships a more mature managed ecosystem, so the right choice depends less on which ORM is "better" in the abstract and more on where the code actually runs and how much SQL fluency the team already has.
Read next:
Follow new articles
Add SciHub101 to your feed reader to see new science and technology stories.
About the Author
SciHub101 is an independent science and technology publication founded and edited by Buğra Sözeri, a software engineer and app developer based in Türkiye. AI tools assist with drafting and research. Source documentation in the existing archive is uneven, and articles are being reviewed and corrected. The Editorial Team byline identifies editorial responsibility; it does not certify specialist or independent human review. Where we compare products, anything built by our own team is labelled as such — see the editorial guidelines and About page for how corrections and disclosures work.
Related Articles

What Is Vite? Modern Frontend Build Tool
Vite is a fast frontend build tool by Evan You using native ESM + esbuild for dev and Rollup for production. How it works and when to use it.

What Is tRPC? End-to-End Typed APIs
tRPC is a TypeScript library for building end-to-end type-safe APIs without code generation, GraphQL schemas, or OpenAPI specs.

ORMs 2026 — Prisma vs Drizzle vs Kysely Honest Comparison
Real comparison of TypeScript ORMs in 2026 — Prisma, Drizzle, Kysely, TypeORM — for type safety, performance, edge compatibility, and migration story.

What Is Hono? Edge-First Web Framework
Hono is a fast, tiny TypeScript web framework that runs on Cloudflare Workers, Deno, Bun, and Node. How it works and when to use it.

SQL for Data Science — Essential Queries to Master
Learn the SQL data scientists use daily: SELECT, JOINs, GROUP BY, window functions, CTEs, and date handling, with PostgreSQL examples and common pitfalls.
