Search selfstore
v1.8.21

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

Use selfstore when

The two coexist fine: keep a big Dexie/IDB dataset for querying, and let selfstore own the app-state loop next to it.