Thorough Comparison of the Best ORMs for the Next.js App Router: How to Choose Between Prisma / Drizzle / Kysely / TypeORM [Part 1]
Introduction
Compared to the traditional Pages Router, the Next.js App Router is significantly changing how routing, data fetching, and server-side logic are structured. Among these changes, “where and how to handle database connections” is a crucial decision point that affects both your app’s architecture and your development experience.
At the center of that decision is the ORM (Object-Relational Mapping).
With options like Prisma, Drizzle ORM, Kysely, and TypeORM available, which ORM actually works best with the App Router’s architecture?
In this article, we’ll thoroughly compare them from the perspectives of implementation ease, type safety, operability, and hosting support, including real code examples.
About this article
This article is the first part of the “Next.js × ORM Comparison” series.
In this first part (this article), we’ll organize the comparison criteria for choosing an ORM that works well with the App Router, and explain the characteristics and differences of each ORM.
In the second part (next time), we’ll build PostgreSQL/MySQL environments with Docker and walk through a hands-on guide where we actually introduce each ORM, run migrations, and implement APIs.
✅ What this article covers
- ORM selection in a Next.js (App Router) environment
- Features and comparison of Prisma / Drizzle ORM / Kysely / TypeORM
- Compatibility with managed databases like Supabase (PostgreSQL) and PlanetScale (MySQL)
- Evaluation axes such as type safety, migrations, lightness, and Edge support
🚫 What this article does not cover
- ORM usage assuming GraphQL (e.g., Hasura / PostGraphile)
- Raw SQL without an ORM, or using Knex alone
- ORM usage with the Pages Router (the traditional Next.js structure)
Background of the comparison
With the Next.js App Router, route handlers (app/api/*/route.ts) and Server Actions make the boundary between React components and backend logic more blurred and flexible.
In this architecture, the following situations occur frequently:
- You want to hit the DB directly on the server side
- You want to fetch data from within UI components via Server Actions
- You want to run logic on Edge Functions, but are concerned about client size and connection counts
Given this background, you need to choose not just an “ORM that works,” but an “ORM that actually meshes well with the Next.js App Router.”
To address those needs, this article dives into an ORM comparison based on real-world use with the App Router, and also covers environment-specific caveats (especially for Supabase / PlanetScale).
Overview of each ORM: Four commonly used options with the Next.js App Router
In this article, we’ll compare the following four ORMs that are often used together with the Next.js App Router.
| ORM | Supported DBs | Features |
|---|---|---|
| Prisma | PostgreSQL, MySQL, SQLite, etc. | Strong type safety, rich documentation, and a GUI management tool. Schema-driven and suited for rapid development. |
| Drizzle ORM | PostgreSQL, MySQL, SQLite | Lightweight with SQL-like syntax. Works very well with the App Router and Edge Functions; rapidly gaining attention. |
| Kysely | PostgreSQL, MySQL, SQLite | Attractive SQL-like DSL and powerful type inference. Characterized by high flexibility and lightness. |
| TypeORM | PostgreSQL, MySQL, SQLite | Decorator-based entity definitions. A long-standing option often used with NestJS, but has some incompatibilities with the App Router. |
All of these are assumed to be used in the following ways within the Next.js App Router:
- Data fetching and creation in API Routes (
app/api/*/route.ts) - Data operations inside Server Actions
- Architectures that run on Edge Functions when needed (especially with Drizzle / Kysely)
Comparison axes: What to look at when choosing an ORM for the Next.js App Router
When comparing ORMs, choosing based only on “ease of use” or “popularity” is not enough.
Especially in the App Router era of Next.js, it’s important to select based on the following perspectives.
Type safety
- Can it auto-generate types from schema definitions?
- How accurate is type inference when writing queries?
| ORM | Type safety |
|---|---|
| Prisma | ◎ |
| Drizzle ORM | ◎ |
| Kysely | ◎ |
| TypeORM | △ |
Notes
- Prisma: Schema-driven type generation is available. High type safety for both models and queries.
- Drizzle: Achieves full type safety based on table structures while using an SQL DSL.
- Kysely: Although SQL-like, it has very powerful type inference that doesn’t depend on raw SQL strings. Types remain stable even with complex JOINs.
- TypeORM: It’s hard to keep entity definitions and query syntax in sync, so mismatches between types and runtime behavior tend to occur.
Compatibility with Edge Functions (lightness and client size)
- If you want to use Edge Functions on hosting platforms like Vercel, you need to pay attention to client size and connection limits.
| ORM | Edge support |
|---|---|
| Prisma | △ |
| Drizzle ORM | ◎ |
| Kysely | ◎ |
| TypeORM | × |
Notes
- Prisma has a large client bundle and is not recommended for Edge Functions.
- Drizzle / Kysely are very lightweight and suitable for Vercel’s Edge Runtime.
- TypeORM has strong Node dependencies and is effectively unusable in Edge environments.
Migration support and DB management
- How are schema changes applied?
- Ease of use of CLI tools and consistency with the DB
| ORM | Migration management |
|---|---|
| Prisma | ◎ |
| Drizzle ORM | ○ |
| Kysely | △ |
| TypeORM | △ |
Notes
- Prisma:
prisma migrate/db pushmake management easy and suitable for production use. - Drizzle:
drizzle-kitcan generate DDL from schemas. Also strong for operations. - Kysely: Official migration support is somewhat awkward. Requires another library or manual management.
- TypeORM: Can generate migrations via CLI, but precision and controllability are somewhat weak.
Ease of implementation with the Next.js App Router
- Does it feel natural to use in API Routes and Server Actions?
- How easy are connection management, initialization, and type definitions?
| ORM | Ease of implementation |
|---|---|
| Prisma | ◎ |
| Drizzle ORM | ◎ |
| Kysely | ○ |
| TypeORM | △ |
Notes
- Prisma / Drizzle: Simple imports and initialization; integration with the App Router feels natural.
- Kysely: Requires a bit more setup for type definitions, but offers high flexibility.
- TypeORM: Requires a DI-like structure, so using it in API routes or Server Actions takes some extra work.
Compatibility with Supabase / PlanetScale (details later)
| ORM | Compatibility with Supabase | Compatibility with PlanetScale |
|---|---|---|
| Prisma | ◎ | △ |
| Drizzle ORM | ◎ | ◎ |
| Kysely | ◎ | ◎ |
| TypeORM | ○ | △ |
Notes
- Prisma is strong with Supabase but has limitations with PlanetScale.
- Drizzle and Kysely work well with both.
- TypeORM is somewhat awkward with both (especially requires caution with PlanetScale).
Based on these comparison axes, the next section will look at “how to write the same data-fetching logic in each ORM.” We’ll also compare how they feel to implement and how readable the code is.
Summary and what’s next
In this article, from the perspective of ORM selection for the Next.js App Router, we compared four major ORMs (Prisma / Drizzle ORM / Kysely / TypeORM) along axes such as type safety, migrations, Edge support, and compatibility with managed databases.
You’ve probably started to see that each ORM has a distinct personality and clear selection criteria.
In the next article, we’ll move to a hands-on format: we’ll spin up PostgreSQL and MySQL with Docker and then, for each ORM in turn, go through introduction, migrations, and API construction.
- How do you run migrations and build APIs with Prisma?
- How do you build schemas from table definitions with Drizzle?
- How do you express the same things with Kysely?
- How do they each feel to write, and what are their design quirks?
We’ll compare these points based on actual implementations.
By digging into even the “hard-to-verbalize differences in development experience,” we hope to give you more concrete material to judge which ORM best fits your project.
👉 The second part is here:
Questions about this article 📝
If you have any questions or feedback about the content, please feel free to contact us.Go to inquiry form
Related Articles
Robust Authorization Design for GraphQL and REST APIs: Best Practices for RBAC, ABAC, and OAuth 2.0
2024/05/13Chat App (with Image/PDF Sending and Video Call Features)
2024/07/15Practical Component Design Guide with React × Tailwind CSS × Emotion: The Optimal Approach to Design Systems, State Management, and Reusability
2024/11/22How to Easily Build a Web API with Express and MongoDB [TypeScript Compatible]
2024/12/09Express (+ TypeScript) Beginner’s Guide: How to Quickly Build Web Applications
2024/12/07Complete Guide to Refactoring React: Improve Your Code with Modularization, Render Optimization, and Design Patterns
2025/01/13Management Dashboard Features (Graph Display, Data Import)
2024/06/02Test Automation with Jest and TypeScript: A Complete Guide from Basic Setup to Writing Type-Safe Tests
2023/09/13