AbsurderSQL: Taking SQLite on the Web Even Further
What if SQLite on the web could be even more absurd?
A while back, James Long blew minds with absurd-sql — a crazy hack that made SQLite persist in the browser using IndexedDB as a virtual filesystem. It proved you could actually run real databases on the web.
But it came with a huge flaw: your data was stuck. Once it went into IndexedDB, there was no exporting, no importing, no backups—no way out.
So I built AbsurderSQL — a ground-up Rust + WebAssembly reimplementation that fixes that problem completely. It’s absurd-sql, but absurder.
Written in Rust, it uses a custom VFS that treats IndexedDB like a disk with 4KB blocks, intell…
AbsurderSQL: Taking SQLite on the Web Even Further
What if SQLite on the web could be even more absurd?
A while back, James Long blew minds with absurd-sql — a crazy hack that made SQLite persist in the browser using IndexedDB as a virtual filesystem. It proved you could actually run real databases on the web.
But it came with a huge flaw: your data was stuck. Once it went into IndexedDB, there was no exporting, no importing, no backups—no way out.
So I built AbsurderSQL — a ground-up Rust + WebAssembly reimplementation that fixes that problem completely. It’s absurd-sql, but absurder.
Written in Rust, it uses a custom VFS that treats IndexedDB like a disk with 4KB blocks, intelligent caching, and optional observability. It runs both in-browser and natively. And your data? 100% portable.
Why I Built It
I was modernizing a legacy VBA app into a Next.js SPA with one constraint: no server-side persistence. It had to be fully offline. IndexedDB was the only option, but it’s anything but relational.
Then I found absurd-sql. It got me 80% there—but the last 20% involved painful lock-in and portability issues. That frustration led to this rewrite.
Your Data, Anywhere.
AbsurderSQL lets you export to and import from standard SQLite files, not proprietary blobs.
import init, { Database } from '@npiesco/absurder-sql';
await init();
const db = await Database.newDatabase('myapp.db');
await db.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
await db.execute("INSERT INTO users VALUES (1, 'Alice')");
// Export the real SQLite file
const bytes = await db.exportToFile();
That file works everywhere—CLI, Python, Rust, DB Browser, etc. You can back it up, commit it, share it, or reimport it in any browser.
Dual-Mode Architecture
One codebase, two modes.
Browser (WASM): IndexedDB-backed SQLite database with caching, tabs coordination, and export/import.
Native (Rust): Same API, but uses the filesystem—handy for servers or CLI utilities.
Perfect for offline-first apps that occasionally sync to a backend.
Multi-Tab Coordination That Just Works
AbsurderSQL ships with built‑in leader election and write coordination:
One leader tab handles writes
Followers queue writes to the leader
BroadcastChannel notifies all tabs of data changes No data races, no corruption.
Performance
IndexedDB is slow, sure—but caching, batching, and async Rust I/O make a huge difference:
Operation | absurd‑sql | AbsurderSQL |
---|---|---|
100k row read | ~2.5s | ~0.8s (cold) / ~0.05s (warm) |
10k row write | ~3.2s | ~0.6s |
Rust From Ground Up
absurd-sql patched C++/JS internals; AbsurderSQL is idiomatic Rust:
Safe and fast async I/O (no Asyncify bloat)
Full ACID transactions
Block-level CRC checksums
Optional Prometheus/OpenTelemetry support (~660 KB gzipped WASM build)
What’s Next
Mobile support (same Rust core compiled for iOS/Android)
WASM Component Model integration
Pluggable storage backends for future browser APIs
GitHub: npiesco/absurder-sql License: AGPL‑3.0
James Long showed that SQLite in the browser was possible. AbsurderSQL shows it can be production‑grade.