ORM · side by side
Drizzle ORM vs Prisma for a Next.js app
Both fill the ORM slot, so a generated repo carries one or the other, never both. Every line below is read out of the two manifests.
Short answer
Pick Drizzle ORM if
Teams who want SQL semantics in TypeScript and serverless deploys without a native binary. Every migration is plain SQL you review in the pull request.
Pick Prisma if
Teams who want one declarative schema file as the source of truth. You get a migration history you can read in review, and a client whose types you never hand-write. Strong pick when several people touch the data model, or when non-backend contributors need Studio to look at rows.
Side by side
Price, obligations, and the surface each one adds. No row is written by hand. This is manifest.yaml, rendered.
| From the manifest | Option ADrizzle ORM | Option BPrisma |
|---|---|---|
| In one line | Drizzle ORM Typed SQL in TypeScript, no engine binary, and migrations you read as plain SQL. | Prisma Schema-first Postgres ORM with generated types, real migrations and a GUI. |
| Pricing | Drizzle ORM Free and open source: drizzle-orm is Apache 2.0 and drizzle-kit is MIT. No hosted service, no seats, no data proxy to pay for. | Prisma Prisma ORM, CLI, migrations and Studio are free and open source (Apache 2.0). Prisma's hosted products (Prisma Postgres, the Accelerate cache) have a free plan, then usage-based paid plans from $10/month. |
| Best for | Drizzle ORM Teams who want SQL semantics in TypeScript and serverless deploys without a native binary. Every migration is plain SQL you review in the pull request. | Prisma Teams who want one declarative schema file as the source of truth. You get a migration history you can read in review, and a client whose types you never hand-write. Strong pick when several people touch the data model, or when non-backend contributors need Studio to look at rows. |
| Trade-offsVerbatim from the manifest | Drizzle ORM
| Prisma
|
| Required companionsAdded for you, with a reason | Drizzle ORM
| Prisma
|
| Recommended alongsideSuggested, never added for you | Drizzle ORM Nothing suggested. | Prisma Nothing suggested. |
| Env vars you will manageEvery one documented in docs/onboard.md | Drizzle ORM 0 variables None. | Prisma 2 variables · 0 required
|
| Dependencies added | Drizzle ORM
| Prisma
|
| MCP serversWritten into .mcp.json | Drizzle ORM None. No extra agent tools from this one. | Prisma None. No extra agent tools from this one. |
| Footprint in your repo | Drizzle ORM 14 files, plus 3 injections into shared stack files | Prisma 13 files, plus 3 injections into shared stack files |
What changes in your repo
The paths each battery contributes, diffed. A path in the third list is written by both, so swapping rewrites that file rather than adding one.
Only with Drizzle ORM (6)
src/3 files
db/3 files
- README.md
- drizzle.ts
- tables.ts
variants/2 files
db-neon/1 file
src/1 file
db/1 file
- migrate.ts
db-supabase/1 file
src/1 file
db/1 file
- migrate.ts
- drizzle.config.ts
Only with Prisma (5)
prisma/2 files
- schema.prisma
- seed.ts
src/2 files
db/2 files
- orm.ts
- prisma.ts
- prisma.config.ts
Same path, different implementation (8)
src/4 files
db/4 files
- audit.ts
- connection-url.ts
- load-env.ts
- verify.ts
variants/4 files
db-neon/2 files
src/2 files
db/2 files
- direct-url.ts
- driver.ts
db-supabase/2 files
src/2 files
db/2 files
- direct-url.ts
- driver.ts
Shared stack files Drizzle ORM injects into
- db-orm
- db-schema
- verify-checks
Shared stack files Prisma injects into
- db-orm
- db-schema
- verify-checks
Drizzle ORM in your .env.local
# Drizzle ORM adds no environment variables.
Prisma in your .env.local
# optional
PRISMA_LOG_QUERIES=0
SEED_ALLOW_REMOTE=0
What changes for your agents
Each battery ships rules, skills, subagents and hooks that an agent loads before it touches the code that battery owns. Picking one is also picking how your agents behave in src/db/**.
Drizzle ORM
2
Skills
2
Rules
5
Solution docs
Rules (2)
Every schema change ships with its generated migration
src/db/** · drizzle/** · drizzle.config.ts
Schema and query conventions for Drizzle
src/db/**
Skills (2)
/add-table
Add a table to the Drizzle schema, generate and apply its migration, and wire the typed queries for it.
/migrate
Generate, review and apply Drizzle migrations safely, including backfills, destructive changes and the deploy step.
Subagents and hooks
None of its own. The foundation agents and guard hooks still ship.
Prisma
2
Skills
2
Rules
5
Solution docs
Rules (2)
Querying with Prisma
src/db/** · src/lib/** · src/app/**
Prisma schema and migrations
prisma/**
Skills (2)
/add-model
Add a Prisma model (or a field on an existing one), migrate it, regenerate the client and wire up the first typed query.
/migrate
Create, inspect, apply and recover Prisma migrations safely: locally, on a branch database and in production.
Subagents and hooks
None of its own. The foundation agents and guard hooks still ship.
What each one already knows
Solution docs land in docs/solutions/ in your repo and are published here, so you can read the failure modes before you commit.
Drizzle ORM (5)
- Adding a NOT NULL column to a table that already has rowsThe one-line migration fails on any populated database. Split it into add-nullable, backfill in batches, and enforce: three migrations across two deploys.docs/solutions/drizzle/adding-a-column-with-a-backfill.md
- drizzle-kit generate or drizzle-kit push, and when each is safepush diffs your schema straight onto the database with no file to review; generate writes SQL you commit. Use push only on a database you can throw away.docs/solutions/drizzle/generate-vs-push.md
- db.query relations or an explicit join: choosing in Drizzle without an N+1The relational API returns nested objects and one round trip; the core builder returns flat rows and total control. Which to reach for, and the loop that quietly becomes N+1.docs/solutions/drizzle/relations-vs-joins.md
- Transactions in Drizzle on serverless: what works over HTTP and what needs a socketAn interactive db.transaction() needs a real connection held open. On an HTTP driver it silently is not one. Here is what each driver supports and how to write atomic writes without holding a connection.docs/solutions/drizzle/transactions-in-serverless.md
- Typing partial selects and joins in Drizzle without writing the types by hand$inferSelect describes the whole row, not the three columns you selected. Use the query builder's inferred types, Awaited<ReturnType<...>>, and helper types instead of hand-maintained interfaces.docs/solutions/drizzle/typing-partial-selects.md
Prisma (5)
- Prisma types are wrong after a schema edit: generated client driftThe Prisma client is generated code. Edit the schema without regenerating and TypeScript describes the old database, locally, in CI-free builds and after a cached deploy.docs/solutions/prisma/client-drift-after-schema-edit.md
- Prisma in dev: "too many clients already" after a few savesNext.js hot reload re-runs your module and builds a new PrismaClient every time. Cache one instance on globalThis and the connection leak stops.docs/solutions/prisma/hot-reload-client-leak.md
- Running Prisma migrations on Vercel without breaking productionPut prisma generate and prisma migrate deploy in the Vercel build command, never db push or migrate dev, and design migrations to survive a rolling deploy.docs/solutions/prisma/migrate-deploy-on-vercel.md
- Fixing N+1 queries in Prisma with include, select and groupByA loop that queries per row turns one page load into hundreds of round trips. Fetch relations in the parent query, batch by id, and aggregate in the database.docs/solutions/prisma/n-plus-one-with-include.md
- Prisma on serverless: why you need a pooler URL and a direct URLEach serverless instance opens its own Postgres pool, so traffic exhausts connections. Route runtime queries through a pooler and keep a direct URL for migrations.docs/solutions/prisma/serverless-connection-pooling.md
Which one to pick
From meta.bestFor and meta.tradeoffs. If a claim is not in the manifest, it is not on this page.
Pick Drizzle ORM when
Teams who want SQL semantics in TypeScript and serverless deploys without a native binary. Every migration is plain SQL you review in the pull request.
And accept that(6)
- No separate schema language: tables are TypeScript, so your editor is the schema editor and there is no codegen step to forget.
- Migrations are generated SQL files you commit and can hand-edit before the first apply. You review the SQL itself, not a diff of a custom format.
- Plain JavaScript with no engine binary, so cold starts on Vercel stay small and edge runtimes work.
- Fewer extras than Prisma: no built-in seeding framework, no data browser beyond drizzle-kit studio, and a smaller plugin ecosystem.
- The relational query API (db.query) is younger than the core builder. Complex aggregate reports still read better as an explicit join or raw sql
. - You own the connection lifecycle. Nothing pools for you, so serverless pooling is a decision you make, not one the ORM hides.
Pick Prisma when
Teams who want one declarative schema file as the source of truth. You get a migration history you can read in review, and a client whose types you never hand-write. Strong pick when several people touch the data model, or when non-backend contributors need Studio to look at rows.
And accept that(5)
- One more schema language to learn.
schema.prismais not TypeScript, so codegen and a generate step sit between you and your types. That is the price of the ergonomics. - A generate step you can forget. Edit the schema without running
bun run db:generateand the client's types still describe the old shape. The error points at your call site, not the schema. - Serverless needs a pooler. On Vercel, point
DATABASE_URLat your database's pooled endpoint for the app. The CLI finds the direct one for migrations throughprisma.config.ts. - No Rust engine at runtime. Prisma 7 plans queries in TypeScript and sends them through a driver adapter for your database, so the app bundle is lighter than Prisma 6's. The CLI still downloads a schema engine binary for migrations.
- Most SQL you need has a first-class API. The rest goes through
$queryRaw, which is less fluent than a SQL-shaped builder.
Questions people actually ask
- Should I choose Drizzle ORM or Prisma?
- Drizzle ORM is best for teams who want SQL semantics in TypeScript and serverless deploys without a native binary. Every migration is plain SQL you review in the pull request. Prisma is best for teams who want one declarative schema file as the source of truth. You get a migration history you can read in review, and a client whose types you never hand-write. Strong pick when several people touch the data model, or when non-backend contributors need Studio to look at rows. Both fill the ORM slot, so a generated repo carries one or the other, never both.
- How much do Drizzle ORM and Prisma cost?
- Drizzle ORM: Free and open source: drizzle-orm is Apache 2.0 and drizzle-kit is MIT. No hosted service, no seats, no data proxy to pay for. Prisma: Prisma ORM, CLI, migrations and Studio are free and open source (Apache 2.0). Prisma's hosted products (Prisma Postgres, the Accelerate cache) have a free plan, then usage-based paid plans from $10/month.
- What changes in my repo if I switch from Drizzle ORM to Prisma?
- Drizzle ORM writes 14 files, 0 environment variables and 2 dependencies, and installs 2 path-scoped rules, 2 skills and 5 solution docs. Prisma writes 13 files, 2 environment variables and 2 dependencies, and installs 2 path-scoped rules, 2 skills and 5 solution docs.
Decide once, then build the repo that already knows the decision.
Either way you get that choice’s rules, skills and solution docs installed, plus the guard hooks, an onboarding doc for exactly these env vars, and the Compound Engineering loop. Free and MIT.