Then on subsequent visits use that server-side data to rehydrate the client-side database.
From https://sqlite.org/forum/info/50a4bfdb294333eec1ba4749661934... is looks like WAL mode is excluded from the default SQLite WASM build so you would have to go custom with that.
In-memory SQLite databases don't use WAL. Wasm (and browser Wasm, in particular) doesn't support anything like the shared memory APIs SQLite wants for its WAL mode.
Litestream requires a very precise WAL setup to work (which just so happens to work with the default native SQLite setup, but is hard to replicate with Wasm).
Cloudflare Durable Objects may have been inspired by Litestream but works very differently (as do LiteFS, Turso, etc…)
The general idea of streaming changes from SQLite would work, but it's a lot of work, and the concurrency model of in-browser Wasm will make it challenging to implement.
(I wrote that forum post some time ago, and have WAL working in a server side Wasm build of SQLite, but none of the options to make it work would make much sense, or be possible, in browser)
I'm gathering that I need to learn about: - WAL - Shared Memory APIs - Concurrency models - Durable Objects?
Shared memory API: If you want to share (mutable) data between multiple processes, you need some kind of procedure in place to manage that. How do you get a reference to the data to multiple processes, how do you make sure they don't trample each other's writes, etc.
Concurrency model: There are many different ways you can formalize concurrent processes and the way they interact (message passing, locking, memory ordering semantics, etc.). Different platforms will expose different concurrency primitives that may not work the same way as other platforms and may require different reasoning or code structure
Durable objects - I think this is some Cloudflare service where they host data that can be read or modified by your users
This is all from memory, but IME, GPT is pretty good for asking about concepts at this level of abstraction
And side note on your last point - I've been burned too many times by confident hallucinations to trust my foundational learning to GPT. I hope someday that will improve, but for now ChatGPT is as trustworthy as an evening chat with someone at the bar.
... Someone who has been drinking since happy hour.
Our database API is modeled on CouchDB and MongoDB, but our storage abstractions are along the lines of what you need to build the multi writer WAL you describe.
More details here https://jsr.io/@fireproof/encrypted-blockstore
I dunno, feels like you're coming down too hard.
https://sqlite.org/wasm/doc/trunk/persistence.md#opfs-wal
Again, just because the all the Lego pieces sound like they should all just fit together, doesn't mean that they will.
The VFS mechanism was primarily designed to make SQLite easy to port to multiple OSes. WAL mode is hard to port everytime you step away from a more traditional OS.
“We have SQLite in the browser, let's just stream the WAL like the Litestream hack” does not add up.
It's not impossible, but it surely took a lot of effort at Cloudflare (or at Fly, or Turso) to get there. And neither of them opened it up sufficiently to help us do the same. In a browser.
You need an identity middle man in front of the Postgres identity to tackle these and validate that the session is still active. Last time I looked at electric it was a big challenge to integrate such a service. This might have improved since then however
> These components were initially released for public beta with version 3.40 and will tentatively be made API-stable with the 3.41 release, pending community feedback.
But the most recent release of SQLite is 3.46.1 (from 2024-08-13)
Presumably they are now "API-stable" but the page hasn't been updated yet.
It would be great if the SQLite team published an official npm package bundling the WASM version, could be a neat distribution mechanism for them. (UPDATE: They do, see replies to this post.)
My favourite version of SQLite-in-WASM remains the Pyodide variant, which has been around since long before the official SQLite implementation. If you use Pyodide you get a WASM SQLite for free as part of the Python standard library - I use that for https://lite.datasette.io/ and you can also try it out on https://pyodide.org/en/stable/console.html
import sqlite3
print(sqlite3.connect(':memory:').execute(
'select sqlite_version()'
).fetchall())
That returns 3.39.0 from 2022-06-25 so Pyodide could do with a version bump. Looks like it inherits that version from emscripten: https://github.com/emscripten-core/emscripten/blob/main/tool...That's correct. i'll try my best to remember to update that reference the next time i'm back on the computer.
> It would be great if the SQLite team published an official npm package
Not a chance. We publish only vanilla JS and adamantly refuse to go down the rabit hole of supporting out-of-language tools (none of which any of our project members use). We support an "officially sanctioned" npm build, maintained by Thomas Steiner, but do not actively develop for any JS frameworks.
Direct support for any given framework (npm included) would give the impression that we endorse that framework, and endorsement of third-party projects is something we actively avoid.
A bit confused at this, NPM is just a package manager / distribution mechanism, not a framework. Totally fair if you don't want to publish for all the package managers, though for Javascript there's only a few that are relevant. NPM has been around for a decade.
It's an out-of-language packaging/distribution framework (and it's not the only one). It's not part of the JS standards.
My comments above have been edited to reframe our stance on npm and frameworks in general.
If you changed the word "framework" to "toolchain" in your post I think it would make a lot more sense to people.
I think they've been doing that for a while, in JS script you can already do this:
import sqlite3InitModule from "https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs";
const sqlite3 = await sqlite3InitModule({
locateFile(file: string) {
return "https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3.wasm";
},
});
// SQLite's C API
const capi = sqlite3.capi;
console.log("sqlite3 version", capi.sqlite3_libversion(), capi.sqlite3_sourceid());
// OO API example below oo1 docs https://sqlite.org/wasm/doc/tip/api-oo1.md
const oo = sqlite3.oo1;
const db = new oo.DB();
const createPersonTableSql = `
CREATE TABLE IF NOT EXISTS person (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER NOT NULL
);
`;
db.exec([createPersonTableSql]);
It works in regular old script tag with type=module, or Deno. I have example HTML here:https://github.com/Ciantic/experimenting-sqlite-wasm/blob/ma...
sqlite-wasm loads much faster than Pyodide, so if you don't need Python, then the former is a better choice.
npm install @sqlite.org/sqlite-wasm
Okay that's listed here: https://sqlite.org/wasm/doc/trunk/persistence.md
EDIT: Self answered.
With the help of Claude, though it incorrectly hallucinated some of the details despite me pasting in documentation: https://gist.github.com/simonw/677c3794051c4dfeac94e514a8e5b...
Though it seems to be somewhat limited. I couldn't even check what version it has, since sqlite_version() was missing. Version in the repository [1] is 3.38.1, which is from quite a ways ago.
At the moment DuckDB web shell can't load SQLite extension, since that hasn't been released for yesterday's 1.1.2. Earlier version does work using recently updated WASM edition. That can be extended with spatial including GDAL, vector search etc [2]. Making your own "SQL web shell" wasn't too hard, though docs weren't quite complete enough for me.
[1] https://github.com/duckdb/sqlite_scanner/blob/main/src/sqlit... [2] https://github.com/duckdb/duckdb-wasm/releases/tag/v1.29.0
You may benefit from perusing the FAQ on that page.
Another issue I have with a lot of the new local first products is that they tend to lock you into a particular database type on the backend, so this is refreshing.
Context: Currently using go-duckdb and while it's working for us, getting rid of cgo would be a huge help. Would be quite interested myself to attempt this.
Wasm is fine for compute (though concurrency is still a somewhat open question).
To have Wasm talk to the outside world, you need “host calls” where the guest calls the host.
On a browser that's Wasm calling JavaScript. On my Go driver, it's Wasm calling Go.
For server side, there's also a standard set of “host calls” modeled around POSIX/Linux syscalls called WASI.
I could've build my project around WASI, but WASI is rather limited (and SQLite support for WASI was more limited even, it's improved a bit since). DuckDB might work out-of-the-box this way.
I, instead, took advantage of SQLite's architecture and replaced its VFS layer with one in Go: https://sqlite.org/vfs.html
So SQLite in Wasm is just doing compute, and I do all the OS level stuff in Go. No need for Wasm concurrency, cause I can load multiple instances of my Wasm which act like independent OS processes that communicate through the filesystem (SQLite excels at this).
As I said, I dunno how well all those decisions would map to DuckDB.
Interesting. So when I am running concurrent readers using your package, it is just loading multiple instances of the wasm code? (I bottleneck to a single writer in the application)
https://github.com/rhashimoto/wa-sqlite/discussions/154
This essentially requires that we import the sqlite emscripten build via an extern C header in wasm bindgen, and then we need to re-implement the VFS in rust while compiling it in multi-threaded mode to allow for shared array buffer access. After that is all done, we will be able to access SQLite rows as raw wasm bytes. That gives us the ability to implement a rust-sqlite style wrapper or integration. There would still not be some of the niceties such as connection pooling, but in wasm you likely want to use the db in exclusive mode.
I'm gearing up for a 0.2 release this week which should iron out a few kinks, but otherwise you can use the diesel ORM as if its native
reliable so far, being dogfooded in production as we speak
More specifically, would this be able to be a "replacement" for indexedDB? Does the data persist, or do I need to keep the sqlite file in the filesytemAPI (or indexedDB/localstorage) myself?
> Specific Goals of this Project
> Insofar as possible, support persistent client-side storage using available JS APIs. As of this writing, that includes the Origin-Private FileSystem (OPFS) and (very limited) storage via the window.localStorage and window.sessionStorage backend.
What I'm asking is if I need to manage the sqlite file, as I would on an OS's file system, or if accessing the sqlite library will automatically persist that data to those web-native storages, like the way indexedDB doesn't require me to load an "idb" file and then "save" or "commit" that save. I just access it and write.
To be clear: I'm not asking academically. I wrote a whole library for managing data in indexedDB for local-first apps, and while it works well enough for what I need, it's iDB so it's subject to data deletion (not common, but allowed in the spec if necessary), and it's a pain to work with just because of its nature and API. So I've been waiting to move to sqlite for a while with the only holdbacks being "is it too heavy?", and "how much has to change?". With WASM, I think we're about as lightweight as its going to get. So I'm just curious if this aims to be a drop-in replacement, or if it still expects you to use it like sqlite on a native platform.
For an in-browser app, that seems a bit much but of course wasm runs in other places these days where it might make more sense.
Adding 400 for such a high quality piece of DB actually borders reasonability.
And makes me think: what the hell are frontend devs thinking!? Multiple MB's in JS for a news website. Hundreds of KB's for HTML. It's totally unreasonable.
I think you can probably blame Tailwind for that.
They're thinking, "adding [some fraction of existing total payload] for such a high quality [feature] actually borders reasonability". Wash. Rinse. Repeat.
If you’re just storing user preferences, obviously don’t download SQLite for your web app just to do that… but if you’re doing something that benefits from a full database, don’t fret so much about 1MB that you go try to reinvent the wheel for no reason.
If the other comment is correct, then it won’t even be 1.3MB on the network anyways.
Also worth considering parsing of wasm is significantly faster than JS (unfortunately couldn't find the source for this claim, there is at lease one great article on the topic)
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_A...
I played around with warm sqlite too. That was really nice but I decided against it due to the fact that it was totally unsupported.
Also, WASI is very far from answer (so far). The SQLite amalgamation builds fine for WASI but concurrency is an unsolved issue.
I had to build a VFS from scratch to get my Wasm based SQLite driver into a usable shape.
https://github.com/ncruces/go-sqlite3/blob/main/vfs/README.m...
In a regular compiler/linker scenario it would just be a static compilation. Here we have a JS app and WASM library.
Is there any hope of that happening? Instead of abstracting and over specifying sqlite, can the spec just specify a version of the SQLite API browsers should support and roll the version periodically?
Even if the spec just listed occasional version and the webpage could choose which one; that means a potentially tricky maintenance burden on browser to support old versions of a potentially no longer supported sqlite, and each version is another megabyte.
Why not then just choose this solution, and let each website pick its own poison?
If the concern is the repeated downloads of common resources, well, we've accepted that for other CDN's too, and a solution for shared caching of common dependencies would in any case be more valuable than merely for sqlite.
The current approach seems better than a browser-provided version.
Now we get the most recent version of SQLite when we need it as a 410KB compressd WASM blob, as opposed to being stuck on browser-mandated versions of SQLite that might even be a decade old at this point.
It's more of an experiment than an attempt to make something production ready, though I could see it being useful to bring dependency-less sqlite tooling to the JVM ecosystem.
When I did this experiment a few months ago, what we could accomplish was pretty limited. I could load and query databases, but not write to them. However the Chicory wasip1 implementation is advancing.
BTW, we've borrowed a few ideas from wazero so thanks for your work there :)
If the goal was pure Java SQLite¹, a VFS from scratch would be better.
I think since I started my Go/wazero effort, WASI+SQLite improved a bunch. I had to start with the demo VFS; the Unix VFS now builds. But custom VFS is still the way to go, IMO.
And thanks! My contributions to wazero were tiny. Best of luck with Chicory!
1: strong NestedVM vibes here; 11 years ago… gosh, I feel old now. https://stackoverflow.com/questions/18186507/pure-java-vs-na...
agreed, though this was more an experiment to test Chicory once we built initial wasi support. I'd love to see it picked up and improved. I think that's the direction I'd go if i want some kind of production ready library.
I can even do Sqlite's full text search without downloading the entire FTS database. Just most of it, if the search term is short enough.
just my intuition when I read the headline of this post - something like the interplay between PouchDB and CouchDB for offline first apps
https://medium.com/offline-camp/couchdb-pouchdb-and-hoodie-a...
Meanwhile for “local-only” it would be great to use sqlite in the browser + native file system API so that the db could be stored on the user’s file system and we wouldn’t have to worry about browser storage eviction. i think that could really open up a whole world of privacy preserving offline software delivered through the browser
[1] https://tetr.app
For the read path it hooks into Postgres logical replication or MongoDB change streams (and MySQL binlog soon). It supports partial syncing using declarative rules. For the write path, it allows writing to the local SQLite database and also places writes into an upload queue, and then uses a developer-defined function to upload writes to the backend API.
We did a deep dive on current options for SQLite on the web, and are currently using an IndexedDB-based VFS, and looking to move to OPFS: https://www.powersync.com/blog/sqlite-persistence-on-the-web
We recently released an integration with TanStack Query to allow leveraging some of its features in conjunction with PowerSync: https://docs.powersync.com/client-sdk-references/js-web/java...
> Meanwhile for “local-only” it would be great to use sqlite in the browser + native file system API so that the db could be stored on the user’s file system and we wouldn’t have to worry about browser storage eviction. i think that could really open up a whole world of privacy preserving offline software delivered through the browser
Agreed. This is a limitation of IndexedDB and OPFS as persistent browser storage currently
From the latest spec [1]:
> The specification reached an impasse: all interested implementors have used the same SQL backend (Sqlite), but we need multiple independent implementations to proceed along a standardisation path.
[1]: https://www.w3.org/TR/webdatabase/
This won't be a problem for wasm SQLite because it isn't a standard being shipped by browsers, just another dependency.
The standardization issues around SQL already exist, are already widely known, and where common workarounds are already in practice. It's also an open source project that could have _easily_ incorporated compatibility code for this specific use case anyways.
They made blind fealty to process more important than the outcome to end users.
What a waste.
I know what you mean here, but I think we're very limited in what we tend to run. Polyglot programming still isn't really a thing, and with things like WASI standardized (someday soon I hope), I could imagine it becoming a lot nicer.
disclaimer: I work there
wow I didn't know this was a thing. thanks for filling me in!
There's a number of WASM platforms/tools: Wasmer, wasmCloud, a few others that escape my memory.
I’m happy that we are actually be able to use SQL in the browser now (although I would rather skip the MBs of the bundle bloat). But I feel like the standards committee will now have even less of a reason to fix the very broken state of IndexedDB.
(Previously discussed 7 months ago: https://news.ycombinator.com/item?id=39477457)