# How context-mode Handles Node.js Version Differences for SQLite Backend Selection

> Discover how context-mode intelligently selects SQLite backends for Node.js, supporting Bun, modern Node.js, and older versions with automatic runtime detection.

- Repository: [Mert Köseoğlu/context-mode](https://github.com/mksglu/context-mode)
- Tags: how-to-guide
- Published: 2026-04-24

---

**`context-mode` uses a lazy-loader in [`src/db-base.ts`](https://github.com/mksglu/context-mode/blob/main/src/db-base.ts) that detects the JavaScript runtime at module initialization, automatically selecting `bun:sqlite` for Bun, `node:sqlite` for Linux Node.js ≥22.5, and falling back to `better-sqlite3` for older versions and other platforms.**

The `mksglu/context-mode` repository abstracts SQLite drivers behind a unified interface to eliminate version-specific dependencies. By implementing runtime detection logic in the database base layer, context-mode ensures optimal backend selection without manual configuration, seamlessly handling the availability of Node.js's built-in `node:sqlite` module while avoiding platform-specific crashes historically associated with native addons on Linux.

## Runtime-Aware SQLite Backend Selection

The library determines which SQLite implementation to load based on three distinct environment checks performed inside the `loadDatabase()` function.

### Bun Runtime Detection

When `(globalThis as any).Bun` evaluates to truthy, context-mode immediately routes to **Bun's native SQLite binding**. The loader imports from `bun:sqlite` and wraps the `Database` constructor with `BunSQLiteAdapter`, providing a `better-sqlite3`-compatible API surface.

### Linux Node.js Version Handling

For Linux platforms (`process.platform === "linux"`), the loader attempts to use **Node.js's built-in `node:sqlite` module** first. This module is only available in Node.js version **22.5 and higher**. The implementation wraps `DatabaseSync` with `NodeSQLiteAdapter` to normalize the API.

If `require(["node", "sqlite"].join(":"))` throws—indicating an older Node.js version without the built-in module—the loader catches the exception and automatically falls back to `better-sqlite3`. This fallback is avoids a known segfault issue (nodejs/node#62515) that affects Linux builds of the native addon.

### Cross-Platform Fallback Strategy

For all other environments—including macOS, Windows, and non-Linux Unix systems—the loader defaults to **better-sqlite3**. These platforms do not have the built-in `node:sqlite` module, and the native addon operates stably outside of the Linux-specific crash scenario.

## The loadDatabase Implementation

The lazy-loader is implemented in [`src/db-base.ts`](https://github.com/mksglu/context-mode/blob/main/src/db-base.ts) (lines 85–103) and executes only once per module lifecycle. The following TypeScript demonstrates the complete detection logic:

```typescript
export function loadDatabase(): typeof DatabaseConstructor {
  if (!_Database) {
    const require = createRequire(import.meta.url);

    if ((globalThis as any).Bun) {
      // Bun → bun:sqlite
      const BunDB = require(["bun", "sqlite"].join(":")).Database;
      _Database = (path, opts) => new BunSQLiteAdapter(new BunDB(path, { readonly: opts?.readonly, create: true }));
    } else if (process.platform === "linux") {
      // Linux Node → try node:sqlite first
      try {
        const { DatabaseSync } = require(["node", "sqlite"].join(":"));
        _Database = (path, opts) => new NodeSQLiteAdapter(new DatabaseSync(path, { readOnly: opts?.readonly ?? false }));
      } catch {
        // node:sqlite not present (older Node) → fallback
        _Database = require("better-sqlite3");
      }
    } else {
      // All other environments → better-sqlite3
      _Database = require("better-sqlite3");
    }
  }
  return _Database!;
}

```

This pattern ensures that **version awareness** is handled at runtime. When running on Node.js versions prior to 22.5, the `require` call for `node:sqlite` throws, and the loader automatically falls back to the native addon without crashing the application.

## Adapter Pattern for API Compatibility

Both `BunSQLiteAdapter` and `NodeSQLiteAdapter` expose an identical surface to the rest of the codebase. According to the source in [`src/store.ts`](https://github.com/mksglu/context-mode/blob/main/src/store.ts), the consuming code interacts with methods like `pragma`, `exec`, `prepare`, `transaction`, and `close` regardless of the underlying driver.

This abstraction guarantees that [`src/store.ts`](https://github.com/mksglu/context-mode/blob/main/src/store.ts) and other consumers remain agnostic to whether they are using Bun's binding, Node.js's native module, or the third-party addon. The adapter layer normalizes differences in constructor signatures and method behaviors, ensuring that **context-mode** delivers consistent performance across all supported platforms.

## Practical Usage Examples

The following examples demonstrate how the runtime-agnostic API works in practice.

### Opening a Database Connection

The same import and initialization code functions identically across Bun, Node.js 22.5+, and older Node.js versions:

```typescript
import { loadDatabase } from "./db-base.js";

const Database = loadDatabase();          // selects appropriate driver automatically
const db = new Database("/tmp/my.db", { timeout: 30_000 });

```

### Executing Queries Across Backends

All adapters support the unified interface for SQL execution:

```typescript
// Works identically on Bun, Linux Node ≥22.5, and other platforms
db.exec(`
  CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT);
  INSERT INTO notes (text) VALUES ('Hello world');
`);

const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(1);
console.log(row); // { id: 1, text: 'Hello world' }

```

### Inspecting the Active Backend

For debugging purposes, you can determine which driver was selected by examining the constructor name:

```typescript
import { loadDatabase } from "./db-base.js";

const Database = loadDatabase();
console.log("Backend:", Database.name); // "BunSQLiteAdapter" | "NodeSQLiteAdapter" | "Database"

```

## Summary

- **[`src/db-base.ts`](https://github.com/mksglu/context-mode/blob/main/src/db-base.ts)** implements a lazy-loader (`loadDatabase()`) that detects Bun via `globalThis.Bun` and Linux Node.js via `process.platform`.
- **Node.js ≥22.5** on Linux uses the built-in `node:sqlite` module to avoid native addon segfaults; older versions fall back to `better-sqlite3`.
- **Bun environments** automatically use `bun:sqlite` wrapped in `BunSQLiteAdapter` for native performance.
- **Adapter classes** normalize the API across all backends, allowing [`src/store.ts`](https://github.com/mksglu/context-mode/blob/main/src/store.ts) to remain driver-agnostic.
- **Test coverage** in [`tests/core/cli.test.ts`](https://github.com/mksglu/context-mode/blob/main/tests/core/cli.test.ts) and [`tests/session-db.test.ts`](https://github.com/mksglu/context-mode/blob/main/tests/session-db.test.ts) validates correct backend selection across simulated runtimes.

## Frequently Asked Questions

### Which Node.js versions support the built-in SQLite backend?

Node.js version **22.5 and higher** includes the built-in `node:sqlite` module. In context-mode, this is only utilized on Linux platforms to avoid stability issues. On older Node.js versions, the library automatically falls back to `better-sqlite3` without requiring code changes.

### Why does context-mode avoid better-sqlite3 on Linux?

The native `better-sqlite3` addon has a documented history of segfaults on Linux builds (nodejs/node#62515). By preferring the built-in `node:sqlite` module on Linux when available, context-mode eliminates the risk of process crashes associated with native addon bindings on this platform.

### How do I verify which SQLite backend is currently active?

After calling `loadDatabase()`, inspect the `name` property of the returned constructor. Values will be `"BunSQLiteAdapter"` when running on Bun, `"NodeSQLiteAdapter"` when using Node.js's built-in module on Linux, or `"Database"` when using the standard `better-sqlite3` fallback.

### Is Bun officially supported by context-mode?

Yes. The source code in [`src/db-base.ts`](https://github.com/mksglu/context-mode/blob/main/src/db-base.ts) explicitly checks for the Bun runtime using `(globalThis as any).Bun` and routes to the `bun:sqlite` module. This is a first-class supported platform, with `BunSQLiteAdapter` providing full API compatibility with the other backends.