A Night to Remember: When Prisma Ate 1GB of Server RAM
2 AM, my phone kept vibrating. The monitoring system signaled a red alert: Memory Usage on Node.js instances spiked to 95%, and latency hit the 5-second mark. After checking the logs, I realized the culprit was Prisma Client. With a schema of over 50 tables and nested include queries, the Prisma engine (written in Rust) consumed massive resources to map the data.
For the next project with 5 developers, I decided to completely change the stack: Ditch the bulky ORM and switch to Kysely. The results were surprising. Team productivity increased significantly. The code ran faster, and most importantly, runtime errors related to the database almost disappeared.
Why Prisma or TypeORM are Gradually Becoming Bottlenecks
Prisma is great for beginners because it hides the complexity of SQL. However, as projects scale, you’ll encounter these practical issues:
- Runtime Overhead: Prisma runs its own query engine as a sidecar process. On AWS Lambda, this increases Cold Start from 200ms to 2-3 seconds.
- Hard to Optimize: Writing Common Table Expressions (CTE) or Window Functions in Prisma is a nightmare. You often have to fall back to
$queryRawand lose all type-safety features. - Loose Type-safety: TypeORM relies heavily on Decorators. Just forgetting one
@Entity(), and the error will only appear when the code is running in production.
Kysely – The Intersection of Pure SQL and TypeScript
Kysely is not an ORM. It is a Type-safe SQL Query Builder. Instead of trying to turn database rows into complex objects, it helps you write SQL directly using TypeScript.
The biggest advantage of Kysely is Zero Runtime Overhead. It is simply a smart SQL string builder. Its bundle size is only a few dozen KB, compared to the tens of MB of the Prisma engine.
Installation and Practical Configuration
If you are using PostgreSQL, install the following packages:
npm install kysely pg
npm install -D @types/pg
Instead of letting the ORM infer everything, we clearly define the table structure via interfaces. This is the single “source of truth” for the entire app:
import { Generated, ColumnType } from 'kysely'
interface UserTable {
id: Generated<number>
email: string
first_name: string | null
created_at: ColumnType<Date, string | undefined, never>
}
export interface Database {
users: UserTable
posts: { id: Generated<number>; title: string; author_id: number }
}
Pro tip: Don’t type it manually if your DB has 100 tables. Use kysely-codegen to scan the DB schema and automatically generate these interfaces in a heartbeat.
Initializing the Kysely Instance
Setting up the connection is very clean:
import { Pool } from 'pg'
import { Kysely, PostgresDialect } from 'kysely'
import { Database } from './types'
const db = new Kysely<Database>({
dialect: new PostgresDialect({
pool: new Pool({ connectionString: process.env.DATABASE_URL }),
}),
})
Coding Experience: When TypeScript Truly Understands Your SQL
The real power emerges when you type db.selectFrom(...). The IDE will suggest the exact table names, column names, and corresponding data types. You will never encounter a typo in a column name again.
Complex Select and Join Example
async function getPostsWithAuthors() {
return await db
.selectFrom('posts')
.innerJoin('users', 'users.id', 'posts.author_id')
.select([
'posts.id',
'posts.title',
'users.first_name as author_name'
])
.where('posts.title', 'like', '%TypeScript%')
.execute()
}
If you rename a column in the DB without updating the interface, TypeScript will immediately flag it with a red error. You can be certain your code will run correctly before deploying.
Why I Chose Kysely for Production Projects?
After 6 months in production, I’ve identified 3 outstanding advantages:
- Absolute Control: I know exactly which SQL query is being executed. Optimizing Indexes or solving N+1 problems becomes more transparent than ever.
- Execution Speed: Queries are executed directly without complex intermediate layers. Latency decreased by an average of 30% compared to using Prisma.
- Advanced SQL Support: Kysely handles Postgres JSONB, Window Functions, or Subqueries exceptionally well without needing unsafe raw strings.
Conclusion: When Should You Switch?
If you are working on a small project (MVP) that needs “instant noodle” speed, Prisma is still fine. But if you are building a high-load system, Serverless, or simply want full control over your source code, Kysely is an option you cannot ignore.
Investing an extra 15 minutes in the initial setup will save you from those midnight calls. Kysely is the ideal intersection between the power of SQL and the safety of TypeScript.

