Running MariaDB in the Browser with WebAssembly Lite4MariaDB, a new open-source project, compiles MariaDB 13.1 to WebAssembly, enabling a full embedded MariaDB server with InnoDB storage to run in browsers and Node.js without a separate server. The ~17 MB module supports transactions, foreign keys, window functions, CTEs, JSON, and vector search, with data persistence via IndexedDB in browsers or file directories in Node. MariaDB, compiled to WebAssembly.Real InnoDB. No server. 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. js 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. js 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. js 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 loading. | 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 |