npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

knex-bun-sqlite

v1.4.0

Published

Use Bun's native high-performance SQLite driver (bun:sqlite) with Knex.js - 3-6x faster than node-sqlite3

Readme

knex-bun-sqlite

Use Bun's native high-performance SQLite driver (bun:sqlite) with Knex.js.

⚡ 3-6x faster than node-sqlite3 while keeping all of Knex's elegant query builder API!

Why?

  • 🚀 Much Faster: Bun's native SQLite is 3-6x faster than node-sqlite3
  • 🎯 Drop-in Replacement: Works with existing Knex code
  • 🪶 Zero Native Dependencies: No need to compile native addons
  • Clean API: Use Knex's query builder with Bun's speed

Installation

bun add knex-bun-sqlite knex

Note: This package requires Bun runtime (v1.0.0+). It uses bun:sqlite which is only available in Bun.

Quick Start

Method 1: Reusable Database Module (Recommended ⭐)

Create a reusable database module for your application - this is the best practice:

// db.js
const knex = require('knex')({
  client: require('knex-bun-sqlite'),  // Clean and simple!
  connection: { filename: './mydb.sqlite' },
  useNullAsDefault: true
})

module.exports = knex

Then in your app:

const db = require('./db')

// Use Knex normally
const movies = await db('movies').where('year', '>', 2000).select('*')
await db.destroy()

Method 2: Module Interception (Alternative)

If you prefer, you can also use module interception to replace sqlite3 automatically:

const KnexBunSqlite = require('knex-bun-sqlite')

// Intercept sqlite3 module loading
const Module = require('module')
const originalRequire = Module.prototype.require

Module.prototype.require = function(id) {
  if (id === 'sqlite3') {
    return KnexBunSqlite.Database  // Use the adapter
  }
  return originalRequire.apply(this, arguments)
}

// Now use Knex normally - it will use bun:sqlite under the hood!
const knex = require('knex')({
  client: 'sqlite3',
  connection: {
    filename: './mydb.sqlite'
  },
  useNullAsDefault: true
})

// All your queries work exactly the same!
async function example() {
  const users = await knex('users').select('*')
  console.log(users)
  await knex.destroy()
}

example()

Features

All Knex operations are fully supported:

  • ✅ SELECT queries with WHERE, JOIN, ORDER BY, LIMIT, etc.
  • ✅ INSERT, UPDATE, DELETE operations
  • ✅ Transactions
  • ✅ Query builder methods
  • ✅ Raw queries
  • ✅ Connection pooling
  • ✅ Proper cleanup with .destroy()
  • ✅ Schema migrations (via SQLite3 in knexfile for CLI, bun:sqlite in your app)

Examples

Basic Queries

const db = require('./db') // Your setup from above

// SELECT
const users = await db('users')
  .where('age', '>', 18)
  .orderBy('name')
  .select('*')

// INSERT
await db('users').insert({
  name: 'Alice',
  email: '[email protected]'
})

// UPDATE
await db('users')
  .where('id', 1)
  .update({ email: '[email protected]' })

// DELETE
await db('users').where('inactive', true).del()

// Always clean up!
await db.destroy()

Migrations

For Knex CLI migrations (running bun knex migrate:latest), use SQLite3 in your knexfile since Knex itself will invoke the SQLite driver:

// knexfile.js - For Knex CLI migrations
module.exports = {
  development: {
    client: 'sqlite3',  // Use standard sqlite3 for CLI
    connection: {
      filename: './dev.sqlite3'
    },
    useNullAsDefault: true
  }
}

Then run migrations with Knex:

knex migrate:latest
knex migrate:rollback
knex seed:run

For your application code, use the reusable database module with knex-bun-sqlite (as shown in Method 1) to get the performance benefits of bun:sqlite while using the same database:

// db.js - Your application's database connection
const knex = require('knex')({
  client: require('knex-bun-sqlite'),  // Use bun:sqlite for speed!
  connection: { filename: './dev.sqlite3' },
  useNullAsDefault: true
})

module.exports = knex

This gives you the best of both worlds: organized migrations with Knex CLI, and blazing-fast queries in your app!

Important: Why Not Use knex-bun-sqlite in knexfile.js?

When you run bun knex migrate:latest or any Knex CLI command, Knex ignores Bun's runtime and invokes Node.js directly to load and execute the migration code. This means:

  • knex-bun-sqlite won't work in your knexfile.js (requires bun:sqlite, which Node.js doesn't have)
  • ❌ You'll get an error: "Cannot find module 'bun:sqlite'"
  • ✅ Use standard sqlite3 in knexfile.js for CLI commands
  • ✅ Use knex-bun-sqlite in your application code (via db.js) for the speed benefits

This is why we recommend the two-pronged approach: SQLite3 for migrations, knex-bun-sqlite for queries!

Transactions

await db.transaction(async (trx) => {
  await trx('accounts')
    .where('id', 1)
    .decrement('balance', 100)
  
  await trx('accounts')
    .where('id', 2)
    .increment('balance', 100)
})

Performance

Benchmark comparison (using Northwind Traders dataset):

| Driver | Read Performance | vs node-sqlite3 | |--------|------------------|-----------------| | bun:sqlite | ⚡ Fastest | 3-6x faster | | better-sqlite3 | Fast | 2x faster | | node-sqlite3 | Baseline | 1x | | deno sqlite | Slow | 0.5x |

Source: Bun's official benchmarks

How It Works

This package creates an adapter that:

  1. Wraps bun:sqlite's synchronous API
  2. Implements the callback-based API that Knex expects
  3. Translates between the two APIs seamlessly
  4. Preserves all Knex functionality

The adapter implements the complete sqlite3 (node-sqlite3) API that Knex uses:

  • Database class with run(), get(), all(), prepare(), etc.
  • Statement class for prepared statements
  • Proper callback context with lastID and changes properties
  • Constants like OPEN_READONLY, OPEN_READWRITE, OPEN_CREATE

API Reference

Database Methods

The adapter provides a sqlite3-compatible Database class:

class Database {
  constructor(filename: string, mode?: number, callback?: (err: Error | null) => void)
  
  run(sql: string, params?: any[], callback?: (this: RunResult, err: Error | null) => void): void
  get(sql: string, params?: any[], callback?: (err: Error | null, row?: any) => void): any
  all(sql: string, params?: any[], callback?: (err: Error | null, rows: any[]) => void): any[]
  each(sql: string, params?: any[], rowCallback?: (err: Error | null, row: any) => void, completeCallback?: (err: Error | null, count: number) => void): void
  exec(sql: string, callback?: (err: Error | null) => void): void
  prepare(sql: string, callback?: (err: Error | null) => void): Statement
  close(callback?: (err: Error | null) => void): void
  serialize(callback?: () => void): void
  parallelize(callback?: () => void): void
}

interface RunResult {
  lastID: number
  changes: number
}

Requirements

  • Bun v1.0.0 or higher - This package uses bun:sqlite which is built into Bun
  • Knex v2.0.0 or higher - For the query builder

Limitations

  • ⚠️ Bun only - This package will not work with Node.js (it requires Bun's native SQLite)
  • ⚠️ Experimental - While extensively tested, there may be edge cases not covered

Troubleshooting

"Cannot find module 'bun:sqlite'"

This means you're not running in Bun. Make sure to use:

bun run your-script.js

Not node your-script.js.

Script doesn't exit

Make sure to call await db.destroy() when you're done:

async function main() {
  // ... your queries
  await db.destroy() // Important!
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Credits

See Also