Kysely: Type-Safe SQL Without ORM Overhead

The bugs I’ve most frequently run into when developing withnamesational databases are easily preventable. These include ones related to queries with mistyped column name, bad assumptions about return types of queries, or a query that “looks right” but returns data in an unexpected form. When the layer for querying the database obscures SQL or shows no type feedback, those mistakes often survive much longer than they should.

That’s why I enjoy using Kysely as a SQL query builder in TypeScript. Without much overhead in terms of installation and setup, it offers strongly typed query results. At the same time, it’s writing queries that feel close to SQL, without committing to a full ORM.

Type Safety that Pays Off Immediately

Kysely’s biggest win for me is that queries are meaningfully type-safe. When I malform a query or select fields that don’t exist, I get TypeScript errors early—before the code ever runs. More importantly, the return types are inferred well. This is particularly significant for more complex joins and selections. When the shape of the result is reflected in the IDE’s code completion/suggestions, developers spend less time guessing what’s coming back and less time adding defensive casting.

In practice, this also makes it harder to write code that inserts or updates invalid data. The query builder becomes a guardrail: if the types don’t line up, it is apparent immediately

In addition to well-typed return values, Kysely also has strongly typed where functions that catch badly formed conditions quickly. These functions are restricted to only three parameters, with the first being the column name, the second being the comparator (‘=’, ‘!=’ ), and the third being the value to compare against. To add multiple filters to a query, multiple where functions should be added to the query. In comparison with other query builders and ORMs, I experienced issues where the where clause function does not error when the input is not formatted correctly. These bugs are tricky to catch, especially when they appear correct, and no errors are shown.

A Thin, Readable Layer Over SQL

Kysely feels like a relatively thin abstraction over SQL. It’s more structured than writing raw strings through pg, but it stays readable as queries get more complex. The chaining model encourages building queries incrementally, and this style feels reliable to me for more complicated conditions and joins. This is also where Kysely’s “not an ORM” posture matters. It doesn’t try to hide SQL behind domain modeling.

For conditional filtering, Kysely is also helpful, as parts of queries can be stored as variables and where clauses can be added optionally until the query is executed using the execute function.

Practical Tooling: Migrations and Type Generation

Kysely’s database migrations feel intuitive to me, with the up function to apply a schema change and down function to revert a schema change. Migration files are generated with the scaffolding for these migration functions, and the functions are written using Kysely. Their model for migrations matches how I already think about schema changes. That means it’s easy to reason about what changes and how to roll them back. Their handling of database migrations (among other things) is similar to Knex, which makes sense as Knex inspired Kysely.

On top of that, Kysely’s type generation based on the current database schema (using kysely-codegen) helps keep the application aligned with the database over time. Having generated interfaces tied to real columns reduces drift and makes “well-typed database code” feel attainable.

A quick comparison note

Some of these benefits overlap with tools like Knex and Drizzle, which also emphasize types. The difference for me is that Kysely stays firmly in the query-builder lane. That simplicity made it easier to spin up a project and focus on safe querying without additional ORM complexity.

Kysely doesn’t fit every project. However, if your team is comfortable with SQL and wants compile-time confidence, readable queries, and lightweight tooling, it’s a strong choice.

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *