Introduction
sql.js is SQLite compiled to WebAssembly via Emscripten. It gives you a complete, standards-compliant SQL database that runs entirely in the browser or in Node.js without any native dependencies. This is useful for client-side data processing, offline apps, and interactive SQL playgrounds.
What sql.js Does
- Provides a full SQLite engine compiled to WebAssembly
- Executes standard SQL queries including joins, indexes, and triggers
- Opens and exports .sqlite / .db files as binary arrays
- Runs in browsers, Node.js, Deno, and web workers
- Requires no server, native bindings, or build toolchain
Architecture Overview
sql.js uses Emscripten to compile the official SQLite C source into a WASM binary. The JavaScript wrapper loads this binary and provides a synchronous API that mirrors the SQLite C interface. The database lives in a WASM linear memory buffer. You can import an existing database from a Uint8Array and export it back for persistence.
Self-Hosting & Configuration
- Install via npm or load the WASM binary from a CDN
- Initialize with
initSqlJs()which fetches and compiles the WASM module - Pass
locateFileto customize where the WASM binary is loaded from - For persistence, export the database to a Uint8Array and save it to IndexedDB, localStorage, or a file
- Run heavy queries in a Web Worker to avoid blocking the main thread
Key Features
- Full SQLite feature set including FTS5, JSON1, and R-Tree extensions
- No native dependencies — works anywhere JavaScript runs
- Import and export .sqlite files as binary arrays
- Synchronous API makes sequential SQL operations straightforward
- WASM binary is under 1 MB gzipped
Comparison with Similar Tools
- Dexie.js — IndexedDB wrapper with a NoSQL-style API; sql.js provides full SQL
- PGlite — embedded Postgres in WASM; sql.js uses SQLite which is lighter
- better-sqlite3 — native Node.js binding; sql.js works in browsers without native code
- absurd-sql — persistence layer on top of sql.js using IndexedDB as a VFS
FAQ
Q: Is data persisted across page reloads? A: Not automatically. The database lives in memory. Export it to IndexedDB or the Origin Private File System for persistence.
Q: How large of a database can sql.js handle? A: It depends on available WASM memory. Databases of tens of megabytes work well; for larger datasets, consider a server-side database.
Q: Can I use existing .sqlite files? A: Yes. Pass the file as a Uint8Array to the Database constructor to open it.
Q: Is sql.js slower than native SQLite? A: WASM adds some overhead, but for typical workloads the difference is small. CPU-intensive queries on large tables will be noticeably slower.