"What do you build the DB layer with on a TypeScript backend?" — this single question shapes development speed, type safety, and operational load for a long time afterward. There are mainly four candidates: Prisma, Drizzle, TypeORM, and Kysely. On social media it tends to become a holy war, but in practice the right answer is to decide quietly by the project's constraints. This article organizes the differences based on each tool's official facts and provides decision axes so you won't second-guess on a project.
I use both Prisma and Drizzle in production, so I'm not in a position to blindly push one. What matters is the discipline of "make the schema the single source of truth, and don't cross boundaries with as/any," and that can be upheld with any tool. An implementation that uses Prisma deeply is in the Prisma ORM production-operations guide (v7); Drizzle is in the Drizzle ORM production-operations guide.
Rules for this article: each tool's category, schema definition, migrations, and type-safety method are based on the respective official documentation (as of June 2026). Maturity numbers like GitHub star counts are rough estimates (aggregated values, not an official API), for reference only. Always confirm the latest in each official source before a final decision.
0. Mental model: the four are not "the same arena"
Let's clear up a misconception first. These four are not side-by-side on features — they're at different abstraction layers.
Kysely (query builder) < Drizzle (SQL-like lightweight ORM) < Prisma / TypeORM (full ORM)
- Kysely is a "type-safe SQL query builder." It's not an ORM. There's no magic for schema management or relation resolution — you write queries in the shape of SQL.
- Drizzle is a "SQL-close lightweight ORM." You write the schema in TypeScript and types flow via inference. It preserves SQL transparency.
- Prisma / TypeORM are "full ORMs." They include relation fetching, migrations, and a model-centric development experience.
Choose not "which is good" but "which abstraction level fits this project" — that's the starting point.
1. The four tools' profiles (official facts)
1.1 Prisma
- Category: a next-generation schema-driven ORM. You declare the data model in the
.prismaDSL and generate a typed client withprisma generate. - Migrations: built in (Prisma Migrate). Edit
schema.prisma→migrate dev. - Type safety: code generation. It provides "full type safety even when you fetch only some columns of a model."
- The v7 evolution: released November 2025. It dropped the Rust engine for a TypeScript + WASM query compiler. In official benchmarks up to 3.4× faster, ~90% smaller bundle (about 14MB → 1.6MB), driver adapter required for all DBs, and edge deployment (Vercel Edge / Cloudflare Workers, etc.) greatly simplified.
- Best fit: "any Node.js / TypeScript backend (including serverless and microservices)." Teams that want the schema as the single source of truth and to reach production fast with managed migrations / connection pooling / caching included.
1.2 Drizzle
- Category: a "headless TypeScript ORM with a head." A lightweight library that flies the banner "if you know SQL you know Drizzle," with both a SQL-like API and relational queries.
- Schema definition: TypeScript (
pgTable(), etc.). Infer types with$inferSelect. No DSL or code generation needed. - Migrations: built in (drizzle-kit). Auto-generates SQL from the TS schema.
- Type safety: inference (no separate generated client needed).
- Lightweightness: its hallmark is the lightness the official site flies as "zero dependencies," "slim," and "serverless-ready" (concrete size figures vary by version).
- Best fit: teams that want type-safe DB access without framework overhead, especially serverless/edge, and who want to stay close to SQL.
1.3 TypeORM
- Category: a decorator-based ORM. It supports "both the DataMapper and ActiveRecord patterns," so you can pick either.
- Schema definition: decorated classes (
@Entity()/@PrimaryGeneratedColumn()/@Column()). - Migrations: built in (CLI, auto-generation supported).
- Type safety: decorators + "full type safety for DB models." Built from scratch in TypeScript.
- Breadth of support: runs on Node.js, browser, mobile, and desktop, and broadly supports MySQL/PostgreSQL/MariaDB/SQLite/MS SQL Server/Oracle/MongoDB/CockroachDB, etc.
- Best fit (editorial): teams comfortable with decorator/ActiveRecord culture (coming from NestJS, Java/Hibernate, Laravel), and situations needing the broadest DB/platform compatibility.
1.4 Kysely
- Category: a "type-safe, autocompleting TypeScript SQL query builder." A Knex-style idea, and not an ORM. Runs on Node.js/Deno/Bun.
- Schema/type definition: given a DB interface (a type), it infers the types of selected columns, aliases, and subqueries (the interface is hand-written, or generated with the third-party
kysely-codegen). - Migrations: a migration runner is built in (
Migrator/migrateToLatest()). Butup/downare hand-written — there's no auto-generation from the schema. - Type safety: inference from the query itself. "The result type holds exactly the selected columns with the correct types."
- Best fit (editorial): teams that want to avoid ORM abstraction and auto-generation, and want control close to raw SQL + full type safety.
2. At-a-glance comparison
| Aspect | Prisma | Drizzle | TypeORM | Kysely |
|---|---|---|---|---|
| Category | Schema-driven ORM | Lightweight SQL-like ORM | Decorator ORM | Query builder |
| Schema definition | .prisma DSL + generation | TS (pgTable) + inference | Decorated classes | Hand-written/codegen interface |
| Migrations | Built in (auto-generated) | Built in (auto-generated) | Built in (auto-generated) | Runner only (hand-written) |
| Source of types | Code generation | Inference | Decorators | Inference |
| Abstraction level | High | Medium | High | Low (SQL itself) |
| Edge/lightweight | Improved by going Rust-free in v7 | Lightweight from the start | Heavier, broad support | Very lightweight |
| What you learn | Learn the DSL | TypeScript only | Decorator conventions | SQL + builder API |
Mind the quality of type safety: all four claim "type safety," but the sources differ. Prisma is a generated artifact, Drizzle/Kysely infer, TypeORM uses decorators. With any method, the moment you bend the result type with
as/any, the safety collapses. This discipline matters to the outcome more than the tool choice.
3. Recommendations by use case
Guidance applied to a situation is more useful than abstraction.
Choose Prisma
- You want a declarative data model as the single source of truth. Your team's SQL proficiency varies.
- You want to run migration operations thickly and safely (reviewable SQL, baselines, zero-downtime migrations).
- You want to reach production fast with Prisma Postgres / Accelerate's managed connection pooling and caching.
- → v7 resolved the edge/serverless weaknesses, so "Prisma for now" is correct more broadly than before.
Choose Drizzle
- You want to preserve SQL transparency. You want to complete things with inference rather than a generated artifact. You want minimal dependencies.
- You want to prioritize lightness on serverless/edge. Your team is good at SQL.
Choose TypeORM
- A decorator-culture stack like NestJS. You're comfortable with ActiveRecord/DataMapper conventions.
- You're continuing an existing TypeORM codebase (hard to make a first choice for greenfield, but reasonable when you have the assets).
Choose Kysely
- You don't want ORM abstraction. You want control close to raw SQL with full type safety.
- Complex queries are the star and you don't need a model-centric development experience.
- → You can also use it alongside Drizzle or Prisma (only heavy queries in Kysely, etc.).
4. Switching cost and a realistic approach
An important fact: Prisma has an official v6→v7 upgrade guide, but there's no official tool-to-tool (Prisma→Drizzle, etc.) migration guide. The "migrating from X to Y" pieces out there are third-party articles, with no official guarantee.
That's exactly why, if you assume a switch, it pays to abstract data access from the start.
// Hide the ORM at the repository layer: callers don't know the ORM (ETC = ease of change)
export interface UserRepository {
findById(id: number): Promise<User | null>;
create(input: NewUser): Promise<User>;
}
// Whether the implementation is Prisma or Drizzle is a matter contained within this layer
export class PrismaUserRepository implements UserRepository {
/* e.g. prisma.user.findUnique(...) */
}
With this in place, swapping the ORM later keeps the impact confined to the repository layer. That said, YAGNI — if there's no migration planned, excessive abstraction is unnecessary. The realistic answer is to choose "the one best now" and keep only the boundary thin.
My stance: tools are to be chosen by constraints, not made into a religion. Don't break type safety with
as/any, make the schema the source of truth, and operate migrations as a review target — with just this discipline, you reach production quality with either Prisma or Drizzle.
5. Selection checklist
- Abstraction level: full ORM (Prisma/TypeORM), SQL-like (Drizzle), or query builder (Kysely) — which layer fits the project
- How you write the schema: DSL + generation (Prisma) / TS inference (Drizzle, Kysely) / decorators (TypeORM) — preference and fit
- Migrations: do you need the thickness of auto-generation (Prisma/Drizzle/TypeORM), or is hand-written operation (Kysely) enough
- Deploy target: is edge/serverless lightness a requirement (Prisma v7, Drizzle, Kysely have the edge)
- Team's grounding: SQL proficiency, framework culture like NestJS
- Managed integration: if you want to ship fast with connection pooling and caching included, Prisma (Postgres/Accelerate)
- Switch tolerance: if a future swap is possible, abstract at the repository layer (if not, don't build it = YAGNI)
- Discipline: whatever you choose — no
as/any, schema as source of truth, review migrations
Summary
Prisma, Drizzle, TypeORM, and Kysely are different categories of tool at different abstraction levels. Prisma is a declarative schema-driven ORM (went Rust-free in v7 and got stronger at the edge), Drizzle is SQL-like and lightweight, TypeORM is decorator culture, and Kysely is a type-safe query builder. Choose not by "which is the most powerful" but by "which abstraction level fits this project's constraints," and you won't fail at selection. And what ultimately divides the outcome is, more than the tool, the discipline of not breaking type safety.
"I want to select a new product's DB layer with future operations in mind" / "I want a third party to verify whether my existing ORM choice is really optimal" — from the project's constraints (deploy target, team, requirements), let's do a tech selection you won't regret together. I bring to your decision the operational know-how from an award-winning product and a payments platform.