DEV Community

Alex Spinov
Alex Spinov

Posted on

Kysely Has a Free API You've Never Heard Of

Kysely is a type-safe TypeScript SQL query builder. No ORM magic, no code generation, no runtime overhead — just a query builder that gives you full TypeScript autocomplete for your database schema.

What Makes Kysely Special?

  • Type-safe SQL — full autocomplete for tables, columns, joins
  • No code generation — types inferred from schema definition
  • Zero runtime overhead — compiles to raw SQL strings
  • Dialect agnostic — Postgres, MySQL, SQLite, MSSQL
  • Composable — build queries dynamically with full type safety

The Hidden API: Type-Safe Query Building

import { Kysely, PostgresDialect } from 'kysely';

interface Database {
  users: { id: number; name: string; email: string; role: 'admin' | 'user'; created_at: Date; };
  posts: { id: number; title: string; content: string; author_id: number; published: boolean; views: number; };
  comments: { id: number; post_id: number; user_id: number; body: string; };
}

const db = new Kysely<Database>({ dialect: new PostgresDialect({ pool }) });

// Full autocomplete — knows every table, column, and type
const posts = await db
  .selectFrom('posts')
  .innerJoin('users', 'users.id', 'posts.author_id')
  .select(['posts.title', 'posts.views', 'users.name as author'])
  .where('posts.published', '=', true)
  .where('posts.views', '>', 100)
  .orderBy('posts.views', 'desc')
  .limit(10)
  .execute();
// TypeScript knows: { title: string; views: number; author: string }[]

// Subqueries
const topAuthors = await db
  .selectFrom('users')
  .select([
    'users.name',
    db.selectFrom('posts')
      .select(db.fn.count('id').as('count'))
      .whereRef('posts.author_id', '=', 'users.id')
      .as('post_count')
  ])
  .orderBy('post_count', 'desc')
  .execute();
Enter fullscreen mode Exit fullscreen mode

Dynamic Query Building

function findPosts(filters: { author?: string; published?: boolean; minViews?: number }) {
  let query = db.selectFrom('posts').selectAll();

  if (filters.published !== undefined) {
    query = query.where('published', '=', filters.published);
  }
  if (filters.minViews) {
    query = query.where('views', '>=', filters.minViews);
  }
  if (filters.author) {
    query = query
      .innerJoin('users', 'users.id', 'posts.author_id')
      .where('users.name', '=', filters.author);
  }

  return query.execute();
}
Enter fullscreen mode Exit fullscreen mode

Quick Start

npm install kysely pg
Enter fullscreen mode Exit fullscreen mode

Why Teams Choose Kysely

A developer shared: "Prisma was great until we needed complex queries — subqueries, CTEs, window functions. Kysely gives us SQL power with TypeScript safety. We write the queries we want, and TypeScript catches mistakes at compile time."


Working with SQL in TypeScript? Email spinov001@gmail.com or check my tools.

ORM or query builder? Kysely vs Drizzle vs Prisma?

Top comments (0)