selfstore vs raw IndexedDB
TL;DR: selfstore IS IndexedDB underneath. The comparison is really "the 500 lines you were about to write" vs "a library that already wrote them".
Respect where due
IndexedDB is the correct storage engine in every browser: asynchronous, transactional, structured-clone-native (real binary data, no base64), gigabyte-capable. selfstore’s working copy is IndexedDB. This page is not IndexedDB versus something else; it is raw usage versus a loop built on it.
What raw IndexedDB hands you
An API from 2010 with events instead of promises, version-upgrade callbacks that brick your app when mishandled, transactions that auto-commit under you, and absolutely nothing above the engine: no backup format, no encryption, no sync, no status, no multi-tab discipline. Every team that ships on raw IDB ends up writing the same five hundred lines, then debugging them in production.
The layer selfstore adds
| Concern | Raw IndexedDB | selfstore |
|---|---|---|
| API | Event-based, version upgrades | Two functions: gather() and apply() |
| Backup | Build your own format | Spec’d encrypted ZIP, one fluent call |
| Encryption | DIY WebCrypto | AES-256-GCM + Argon2id, in a worker |
| Sync | None | Deterministic HLC merge, five strategies |
| Multi-tab | DIY locks | Web Lock + BroadcastChannel, built in |
| Schema evolution | onupgradeneeded | schemaVersion + migrate(), SCHEMA_TOO_NEW guard |
| Status for the UI | None | Headless descriptor |
Use raw IndexedDB (or a query wrapper) when
- You have a large, queryable dataset: tens of thousands of records, indexes, cursors, range scans. selfstore’s snapshot model is deliberately whole-state and memory-bound; it is not a query engine. (For that need, also look at Dexie, which we recommend without irony.)
Use selfstore when
- The job is “persist my app’s state, durably, privately, portably”, not “query a million rows”.
- You want the user to hold a real backup file, and maybe open the same data on a second device, without operating servers.
The two coexist fine: keep a big Dexie/IDB dataset for querying, and let selfstore own the app-state loop next to it.