← Back to archive

Repo of the Day

sql-js/sql.js

Published: Mar 12, 2026

Open repository ↗

A javascript library to run SQLite on the web.

Summary

sql.js compiles SQLite to WebAssembly so it can run as a JavaScript library in the browser or in Node.js, without a server-side database. It exposes an API for creating tables, running prepared statements with named or positional parameters, and exporting the database as a Uint8Array.

What it is useful for

sql.js fits situations where you want a relational engine inside a web page or a Node script: opening a prebuilt SQLite file the user supplies, running SQL against uploaded data in a client-side tool, or prototyping queries in a sandbox without spinning up a backend. Because it runs on top of a virtual in-memory file system provided by Emscripten, the database is held entirely in RAM and changes do not persist unless you explicitly call db.export(). The README notes that for native applications (Electron) or production Node.js workloads, a native binding such as the sqlite3 package will generally be faster and can read databases without pulling them fully into memory. The library also bundles SQLite's contributed math and string extension functions.

How engineers can use it

In Node.js, install with npm install sql.js and load the library asynchronously:

const initSqlJs = require('sql.js');
const SQL = await initSqlJs();
const db = new SQL.Database();
db.run("CREATE TABLE hello (a int, b char); INSERT INTO hello VALUES (0, 'hello');");
const stmt = db.prepare("SELECT * FROM hello WHERE a=:aval AND b=:bval");
console.log(stmt.getAsObject({':aval' : 1, ':bval' : 'world'}));
stmt.free();

You can register a JavaScript function for use inside SQL with db.create_function("add_js", add) and define custom aggregate functions via db.create_aggregate, passing init, step, and finalize callbacks. To load a .sqlite file in the browser, fetch it and pass the resulting Uint8Array to new SQL.Database(...); to save work, call db.export() and write the typed array back out.

The README documents several constraints to plan around: the WebAssembly build requires shipping both sql-wasm.js and sql-wasm.wasm, the in-memory model means the dataset must fit in RAM, and in 1.x NOTHING is now a reserved word. BigInt is described as partially supported, with binding not yet implemented though retrieval works when useBigInt: true is passed. For heavier queries, a Web Worker build is also distributed.