Getting started
Kysely has built-in support for PostgreSQL, MySQL and SQLite. To install it run:
# PostgreSQL
npm install kysely pg
# MySQL
npm install kysely mysql2
# SQLite
npm install kysely better-sqlite3
Kysely also has a simple interface for 3rd party dialects.
3rd party dialects
- PlanetScale Serverless Driver
 - Cloudflare D1
 - AWS RDS Data API
 - SurrealDB
 - Neon
 - AWS S3 Select
 - libSQL/sqld
 - SingleStore Data API
 - Postgres.js
 - Fetch driver
 
Minimal example
import { Pool } from 'pg'
import {
  Kysely,
  PostgresDialect,
  Generated,
  ColumnType,
  Selectable,
  Insertable,
  Updateable,
} from 'kysely'
interface PersonTable {
  // Columns that are generated by the database should be marked
  // using the `Generated` type. This way they are automatically
  // made optional in inserts and updates.
  id: Generated<number>
  first_name: string
  gender: 'male' | 'female' | 'other'
  // If the column is nullable in the database, make its type nullable.
  // Don't use optional properties. Optionality is always determined
  // automatically by Kysely.
  last_name: string | null
  // You can specify a different type for each operation (select, insert and
  // update) using the `ColumnType<SelectType, InsertType, UpdateType>`
  // wrapper. Here we define a column `modified_at` that is selected as
  // a `Date`, can optionally be provided as a `string` in inserts and
  // can never be updated:
  modified_at: ColumnType<Date, string | undefined, never>
}
interface PetTable {
  id: Generated<number>
  name: string
  owner_id: number
  species: 'dog' | 'cat'
}
interface MovieTable {
  id: Generated<string>
  stars: number
}
// Keys of this interface are table names.
interface Database {
  person: PersonTable
  pet: PetTable
  movie: MovieTable
}
// You'd create one of these when you start your app.
const db = new Kysely<Database>({
  // Use MysqlDialect for MySQL and SqliteDialect for SQLite.
  dialect: new PostgresDialect({
    pool: new Pool({
      host: 'localhost',
      database: 'kysely_test',
    }),
  }),
})
async function demo() {
  const { id } = await db
    .insertInto('person')
    .values({ first_name: 'Jennifer', gender: 'female' })
    .returning('id')
    .executeTakeFirstOrThrow()
  await db
    .insertInto('pet')
    .values({ name: 'Catto', species: 'cat', owner_id: id })
    .execute()
  const person = await db
    .selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    .select(['first_name', 'pet.name as pet_name'])
    .where('person.id', '=', id)
    .executeTakeFirst()
  if (person) {
    person.pet_name
  }
}