Kysely is a type-safe SQL query builder for Node.js that brings strong TypeScript support and a clean, flexible API.
Kysely includes everything you'd expect from a modern query builder: strong type safety, easy-to-read queries, transaction support, and built-in migration tools.
In this guide, you’ll learn how to use Kysely with SQLite—from simple queries to more advanced operations—through clear, step-by-step examples.
Prerequisites
To follow this article, you'll need:
- A recent version of Node.js
- Basic SQL and database knowledge
- Familiarity with TypeScript
Step 1 — Setting up your project
Before using Kysely, let’s set up a fresh project environment. In this guide, we’ll build a simple bookstore management system using Kysely with SQLite. This setup gives you a lightweight yet powerful local database perfect for development and learning.
Start by creating a new project directory:
Initialize a new npm project:
Install Kysely and SQLite dependencies:
Install TypeScript development dependencies:
Create a TypeScript configuration file and add the following configuration to tsconfig.json:
This configuration enables modern JavaScript features and strict type checking for improved code quality.
Step 2 — Connecting to the database and creating a table
Before you start writing any queries, it’s essential to understand what makes Kysely stand out. Kysely is a query builder—it gives you full control over your SQL while ensuring TypeScript catches mistakes early, before your code even runs.
First, let’s make a directory to keep all your code organized.
Now, create a src/database.ts database connection file and add the following code to set up our bookstore database schema:
This code does three important things:
- Defines a TypeScript interface for our database schema, which enables compile-time checking
- Creates a SQLite database file named
bookstore.db(it will be created if it doesn't exist) - Initializes Kysely with the SQLite dialect
When you import this db object in other files, TypeScript will know precisely what tables and columns exist in your database, preventing many common errors.
Now let's create a file to set up our books table:
Add the following code to create our table:
The db.schema.createTable() method provides a fluent interface for defining your table structure. The ifNotExists() method ensures the script won't fail if you run it multiple times. Each addColumn() call defines a column with its data type and constraints.
Run this script to create your table:
Behind the scenes, Kysely generates and executes the following SQL:
A new SQLite database file named bookstore.db will be created in your project directory.
Step 3 — Creating Records
Now that your books table is ready, let’s add some sample data. In this step, you’ll insert multiple book records into the database using Kysely's clear and type-safe API.
Create a new src/add-books.ts file to handle the insertion with the following code to bulk insert books:
In this script, you’re inserting two book records in one go using Kysely’s insertInto().values().execute() chain. Once the data is inserted, the database connection is closed with db.destroy().
To run the script:
You should see output like this:
Step 4 — Querying Records
After adding data to your database, the next step is to retrieve it. In this section, you'll use Kysely's powerful query features to select and filter data from your SQLite database.
Create a new src/query-books.ts file for your query operations with the following code:
In this example, you retrieve all records using selectAll(), which works like SELECT * FROM books.
Run the script to see the results:
The output will show all book records currently stored in your database, like this:
You can also filter the results. For example, if you want to find books by a specific author, use the where() method like so:
And if you want to list books that cost less than $30, sorted by price in ascending order:
Kysely's query builder makes database operations intuitive while providing complete type safety.
If you try to reference a non-existent column in your query, TypeScript will catch the error during development, preventing runtime issues.
Step 5 — Updating records
After inserting and querying data, the next step is updating it. In this section, you’ll learn how to modify existing book records using Kysely’s fluent, SQL-like update syntax with full TypeScript support.
Start by creating a new src/update-books.ts file to handle updates:
In this script, you're performing a simple update—changing the price of a specific book using a fixed value. The .set() method updates the field, while .where() ensures only the matching row is affected.
To run the script:
You should see output like this:
As you can see, the price for SQL Database Design has been updated to $39.99.
If you want to update multiple records based on a condition—for example, applying a discount to all books over $30—you can use an expression-based update like this:
In this example, you're applying a 10% discount to all books priced over $30. Kysely allows you to perform calculations directly in the database using expression helpers like db.ref() to reference a column and db.fn.val() to wrap the result.
This approach is both efficient and concise—there’s no need to fetch records into JavaScript, update them manually, and write them back. Everything happens within a single SQL query.
Step 6 — Deleting Records
To wrap up the CRUD operations, let’s look at how to delete records from your database. In this step, you’ll use Kysely’s deleteFrom() method to remove books based on specific conditions.
Start by creating a new src/delete-books.ts file:
In this script, you use deleteFrom() with a where() clause to remove books written by David Wilson. The result tells you how many rows were deleted. After the deletion, the script fetches and prints the remaining books to confirm the update.
To run the script:
Output:
As you can see, the book by David Wilson has been successfully removed.
Final thoughts
In this guide, you learned how to use Kysely with SQLite and TypeScript to build a simple app with full CRUD functionality. Kysely gives you control over SQL and the safety of TypeScript.
Want to go further? Kysely also supports joins, subqueries, transactions, and more. To explore advanced features, check out the official docs.