SQLite.Encrypted for Node.js

@sqlite-encrypted/node provides the synchronous DatabaseSync and StatementSync API modeled on Node.js 22 node:sqlite, backed by prebuilt SEE native libraries.

Core rule: Import this package instead of node:sqlite, activate SEE, then pass key to DatabaseSync.

Codec support: SQLite.Encrypted currently supports only aes256ofb. Omit the codec or pass null to use aes256ofb; any codec supplied to key() or rekey() must be aes256ofb. Keyed constructors use the same aes256ofb default.

Install

Configure the SQLite.Encrypted npm scope in the project's .npmrc:

@sqlite-encrypted:registry=https://packages.sourcegear.com/npm/

Then install the package:

npm install @sqlite-encrypted/node

The package contains prebuilt binaries and has no runtime npm dependencies. It does not invoke node-gyp during installation.

Supported prebuilds are Windows x64, macOS x64 and ARM64, and glibc Linux x64 and ARM64. Alpine and other musl Linux distributions are not supported.

Open and query an encrypted database

The ordinary DatabaseSync and StatementSync APIs are unchanged.

const {
  DatabaseSync,
  activateSEE,
} = require('@sqlite-encrypted/node');

activateSEE(process.env.SQLITE_SEE_ACTIVATION_KEY);

const database = new DatabaseSync('application.db', {
  key: process.env.DATABASE_KEY,
});

database.exec(`
  CREATE TABLE IF NOT EXISTS notes (
    id INTEGER PRIMARY KEY,
    body TEXT NOT NULL
  )
`);

const insert = database.prepare('INSERT INTO notes(body) VALUES (?)');
insert.run('hello');

const rows = database.prepare(
  'SELECT id, body FROM notes ORDER BY id'
).all();

database.close();

The constructor applies key through database.key() and propagates a native key-loading failure. Omit key to open a plaintext database. Opening without key and calling database.key() immediately is the preferred alternative when the key is not available at construction time.

Open with PRAGMA

Open without a key, then execute both statements before preparing or executing schema queries. Verify that the key PRAGMA returns ok.

const { DatabaseSync } = require('@sqlite-encrypted/node');

const database = new DatabaseSync('legacy.db');
database.exec(
  "PRAGMA activate_extensions = 'see-<activation-key>'"
);
const keyRow = database.prepare(
  "PRAGMA key = '<database-key>'"
).get();
if (!keyRow || Object.values(keyRow)[0] !== 'ok') {
  throw new Error('SEE did not accept the database key');
}

On a build without encryption support, or when SEE cannot load the key, the key PRAGMA returns no row. Ignoring that result can leave the application using a connection whose encryption key was never applied. Prefer the constructor key option or database.key() for new integrations.

Text, binary, and null keys

const database = new DatabaseSync('existing.db');

database.key(null, 'initial text key');
database.rekey(null, Uint8Array.from([0x01, 0x00, 0x7f, 0xff]));
database.rekey(null, 'replacement text key');
database.rekey(null, null);

Strings use SEE text-key semantics. Uint8Array preserves the exact bytes and length. Null removes encryption. Pass null as the database name and omit the codec to use the main database and the aes256ofb default.

database.rekey('main', 'replacement key', 'aes256ofb');

Encrypt a backup

const { backup } = require('@sqlite-encrypted/node');

await backup(database, 'application-backup.db', {
  key: process.env.BACKUP_KEY,
});

Omitting the backup key creates a plaintext destination. An encrypted backup requires prior SEE activation.

Select a native library explicitly

Normal installations select the packaged library automatically. To test or diagnose a specific build, use an option or environment variable.

activateSEE(process.env.SQLITE_SEE_ACTIVATION_KEY, {
  nativeLibrary: '/absolute/path/to/e_sqlite3',
});
SQLITE_ENCRYPTED_LIBRARY=/absolute/path/to/e_sqlite3 node application.js

SQLITE_ENCRYPTED_LIBRARY selects the SQLite.Encrypted native library used by this package. It does not cause the built-in node:sqlite module to use SEE.

Compatibility note

This package is a compatibility implementation, not a replacement binary for Node's built-in module. It covers the main synchronous database and statement surface, sessions, changesets, functions, extensions, and online backup. Check the package release notes before relying on a newer node:sqlite API.