Last Updated: 3/20/2026
Runtimes
Kysely is a pure TypeScript library with zero dependencies, which means it runs in any JavaScript runtime. The core query builder works identically across Node.js, Deno, Bun, Cloudflare Workers, and browsers. The only runtime-specific component is the database driver.
Node.js
Node.js is the primary runtime for Kysely. The minimum supported version is 20.0.0 (as specified in package.json). Install Kysely from npm:
npm install kyselyUse with your preferred database driver:
import { Kysely, PostgresDialect } from 'kysely'
import { Pool } from 'pg'
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({
connectionString: process.env.DATABASE_URL
})
})
})Kysely provides built-in dialects for PostgreSQL (pg), MySQL (mysql2), SQLite (better-sqlite3), and MS SQL Server (tedious). Each dialect wraps the corresponding Node.js driver.
Deno
Kysely is published to JSR (JavaScript Registry) as @kysely/kysely. Import it in Deno using the JSR specifier:
import {
Kysely,
PostgresAdapter,
PostgresIntrospector,
PostgresQueryCompiler,
DummyDriver,
Generated
} from 'jsr:@kysely/kysely'
interface Database {
person: {
id: Generated<number>
first_name: string
last_name: string | null
}
}
const db = new Kysely<Database>({
dialect: {
createAdapter: () => new PostgresAdapter(),
createDriver: () => new DummyDriver(),
createIntrospector: (db) => new PostgresIntrospector(db),
createQueryCompiler: () => new PostgresQueryCompiler()
}
})
const query = db.selectFrom('person').select('first_name')
console.log(query.compile().sql)This example uses DummyDriver to create a “cold” Kysely instance that compiles queries without executing them. To execute queries in Deno, you need a Deno-compatible database driver.
Community drivers for Deno:
- PostgreSQL: Use
postgresfrom deno.land/x or implement a custom driver wrapping Deno’s native PostgreSQL client - SQLite: Use
sqlitefrom deno.land/x
The JSR package (defined in jsr.json) includes all Kysely source files and helper modules for each dialect.
Bun
Bun supports Node.js-compatible packages, so you can install Kysely from npm and use it with Node.js drivers:
bun add kysely
bun add pgimport { Kysely, PostgresDialect } from 'kysely'
import { Pool } from 'pg'
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({
connectionString: process.env.DATABASE_URL
})
})
})
const result = await db
.selectFrom('person')
.selectAll()
.execute()Bun’s runtime is highly compatible with Node.js, so most Node.js database drivers work without modification. Bun also provides its own native SQLite driver (bun:sqlite) which can be wrapped in a custom Kysely driver.
Cloudflare Workers
Kysely runs in Cloudflare Workers, but you need a driver compatible with the Workers runtime. Cloudflare Workers don’t support TCP connections, so traditional database drivers like pg won’t work.
Options for Cloudflare Workers:
D1 (Cloudflare’s SQLite): Use the kysely-d1 community package to connect to Cloudflare D1 databases:
import { Kysely } from 'kysely'
import { D1Dialect } from 'kysely-d1'
export default {
async fetch(request: Request, env: Env) {
const db = new Kysely({
dialect: new D1Dialect({ database: env.DB })
})
const result = await db
.selectFrom('person')
.selectAll()
.execute()
return new Response(JSON.stringify(result))
}
}HTTP-based drivers: Use drivers that connect to databases over HTTP, such as @neondatabase/serverless for Neon’s PostgreSQL or @planetscale/database for PlanetScale’s MySQL.
Query building only: Use DummyDriver to build queries in Workers and execute them in a different environment (like a backend service).
Browsers
Kysely runs in browsers when paired with a browser-compatible database driver. The most common use case is SQLite via WebAssembly:
import {
Kysely,
DummyDriver,
SqliteAdapter,
SqliteIntrospector,
SqliteQueryCompiler,
Generated
} from 'kysely'
interface Database {
person: {
id: Generated<number>
first_name: string
last_name: string | null
}
}
const db = new Kysely<Database>({
dialect: {
createAdapter: () => new SqliteAdapter(),
createDriver: () => new DummyDriver(),
createIntrospector: (db) => new SqliteIntrospector(db),
createQueryCompiler: () => new SqliteQueryCompiler()
}
})
const sql = db.selectFrom('person').select('id').compile()
console.log(sql.sql) // Display in the browserThis example uses DummyDriver to compile queries without executing them. To execute queries in the browser, use a WebAssembly-based SQLite driver like sql.js or wa-sqlite, wrapped in a custom Kysely driver.
Browser-compatible drivers:
- sql.js: SQLite compiled to WebAssembly
- wa-sqlite: Another SQLite WebAssembly implementation
- IndexedDB: Wrap IndexedDB in a custom driver for client-side storage
You can also use Kysely in the browser to build queries that are sent to a backend API for execution.
Runtime Differences
The core Kysely API is identical across all runtimes. The only differences are:
Module system: Node.js supports both CommonJS and ES modules. Deno and browsers use ES modules only. Kysely’s package.json exports both formats for Node.js compatibility.
Database drivers: Each runtime requires compatible drivers. Node.js drivers use TCP connections. Cloudflare Workers and browsers need HTTP-based or WebAssembly drivers.
File system access: Migrations that read from the file system (like FileMigrationProvider) only work in Node.js and Deno. Use alternative migration strategies in browsers and Workers.
Environment variables: Access to process.env varies by runtime. Use runtime-specific APIs (like Deno.env or Cloudflare Workers’ env bindings) to access configuration.
Building for Multiple Runtimes
If you’re building a library or application that runs in multiple runtimes, structure your code to abstract the runtime-specific parts:
// db.ts - Runtime-agnostic query definitions
import { Kysely } from 'kysely'
export function createQueries<DB>(db: Kysely<DB>) {
return {
async getPerson(id: number) {
return await db
.selectFrom('person')
.selectAll()
.where('id', '=', id)
.executeTakeFirst()
}
}
}
// node.ts - Node.js-specific setup
import { Kysely, PostgresDialect } from 'kysely'
import { Pool } from 'pg'
import { createQueries } from './db'
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({ connectionString: process.env.DATABASE_URL })
})
})
export const queries = createQueries(db)
// deno.ts - Deno-specific setup
import { Kysely } from 'jsr:@kysely/kysely'
import { createQueries } from './db.ts'
// ... Deno-specific driver setupThis pattern keeps your query logic portable while isolating runtime-specific driver configuration.
Package Distribution
Kysely is distributed through multiple channels:
- npm:
kyselypackage for Node.js and Bun - JSR:
@kysely/kyselyfor Deno - CDN: Available via jsdelivr and other CDNs for browser use
The npm package includes both CommonJS (dist/cjs/) and ES module (dist/esm/) builds. The JSR package includes TypeScript source files that Deno compiles on-the-fly.
What’s Next
- Dialects: Learn about the built-in dialects for PostgreSQL, MySQL, SQLite, and MS SQL Server.
- Extending Kysely: Implement a custom driver for a database or runtime not supported by Kysely’s built-in dialects.
- Migrations: Set up database migrations in different runtime environments.