The SQL Builder Problem
Knex: great builder, returns any. Prisma: full ORM, can't write raw SQL easily. TypeORM: decorators, magic strings. Raw SQL: no autocomplete, no type checking.
Kysely is a type-safe SQL query builder. Full TypeScript autocomplete for table names, column names, and result types. Zero runtime overhead.
What Kysely Gives You
Type-Safe Queries
import { Kysely, PostgresDialect } from 'kysely';
interface Database {
users: {
id: number;
name: string;
email: string;
created_at: Date;
};
posts: {
id: number;
title: string;
author_id: number;
};
}
const db = new Kysely<Database>({ dialect: new PostgresDialect({ pool }) });
// Full autocomplete: table names, column names
const users = await db
.selectFrom('users')
.select(['id', 'name', 'email'])
.where('email', 'like', '%@company.com')
.orderBy('created_at', 'desc')
.execute();
// users is typed as { id: number; name: string; email: string }[]
Joins With Types
const results = await db
.selectFrom('posts')
.innerJoin('users', 'users.id', 'posts.author_id')
.select(['posts.title', 'users.name as author'])
.execute();
// results: { title: string; author: string }[]
Column names from both tables available with autocomplete.
Insert, Update, Delete
await db.insertInto('users').values({
name: 'John',
email: 'john@example.com',
}).execute();
await db.updateTable('users')
.set({ name: 'Jane' })
.where('id', '=', 1)
.execute();
await db.deleteFrom('users')
.where('id', '=', 1)
.execute();
Subqueries
const result = await db
.selectFrom('users')
.select([
'name',
(eb) => eb.selectFrom('posts')
.select(eb.fn.count('id').as('count'))
.whereRef('posts.author_id', '=', 'users.id')
.as('post_count'),
])
.execute();
Raw SQL When Needed
const result = await sql<{ count: number }>`
SELECT COUNT(*) as count FROM users WHERE created_at > ${date}
`.execute(db);
Migrations
export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('users')
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('name', 'text', (col) => col.notNull())
.addColumn('email', 'text', (col) => col.unique().notNull())
.execute();
}
Works With
PostgreSQL, MySQL, SQLite, MSSQL. Works on Node, Deno, Bun, Cloudflare Workers.
Quick Start
npm install kysely pg
Why This Matters
SQL is the best query language. The problem was never SQL — it was the lack of type safety. Kysely adds TypeScript to SQL without adding ORM complexity.
Need data for your SQL databases? Check out my web scraping actors on Apify Store — structured data ready for import. For custom solutions, email spinov001@gmail.com.
Top comments (0)