A full MariaDB embedded server that runs in the browser and in Node.js, with a PGlite-style JavaScript API. Transactions, foreign keys, window functions, CTEs, JSON and vector search — in one ~17 MB module.
InnoDB
Transactions, foreign keys, crash recovery. The real storage engine, not a shim.
memory · file · idb
Ephemeral by default, a directory in Node, IndexedDB in the browser. Snapshots as gzipped tar.
MariaDB 13.1
Window functions, CTEs, JSON functions and native vector search, unchanged.
Browser + Node ≥ 18
Main thread or a worker with the same API. One .wasm module plus a thin wrapper.
import { Lite4MariaDB } from 'lite4mariadb';
const db = await Lite4MariaDB.create({ dataDir: './my-data' });
db.exec('CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(64)) ENGINE=InnoDB');
db.exec('INSERT INTO users VALUES (?, ?)', [1, "O'Brien"]);
const rows = db.query('SELECT * FROM users WHERE id = ?', [1]);
// => [ { id: 1, name: "O'Brien" } ]
await db.close();
A datadir that already holds a database is resumed on open — InnoDB recovery runs, and your data is back.
import { Lite4MariaDB } from 'lite4mariadb';
// one IndexedDB database per name
const db = await Lite4MariaDB.create({ dataDir: 'idb://my-app' });
db.exec('CREATE TABLE notes (id INT AUTO_INCREMENT PRIMARY KEY, body TEXT)');
db.exec('INSERT INTO notes (body) VALUES (?)', ['hello from the tab']);
await db.persist(); // hard flush; writes are otherwise debounced
await db.close();
The build uses pthreads, so serve with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp.
import { Lite4MariaDBWorker } from 'lite4mariadb/worker';
// same API, every method async, main thread stays free
const db = await Lite4MariaDBWorker.create({ dataDir: 'idb://my-app' });
const rows = await db.query('SELECT * FROM users');
await db.close();
Works in Node via worker_threads too. Pass your own Worker running dist/worker-entry.mjs as the second argument to customize .
| create(opts?) | memory:// (default), file:// in Node, idb:// in the browser | | query(sql, params?) | Rows as objects, coerced JS types | | exec(sql, params?) | { ok, affected, rows, fields } | | execMulti(sql) | A whole script, one result per statement | | transaction(cb) | BEGIN / COMMIT, ROLLBACK on throw | | dumpDataDir() | Gzipped tar snapshot, restorable via loadDataDir | | close() | Flushes idb:// first |