Compatibility
What CI actually proves, per engine and per environment.
Every claim in the first table is exercised by CI on every commit — the lifecycle journey (open → set → reload → same value, then update, reset, destroy) runs in Chromium, Firefox, and WebKit via Playwright.
| Feature | Chromium | Firefox | WebKit |
|---|---|---|---|
| IndexedDB open + read + write | Yes | Yes | Yes |
| Atomic readwrite transaction | Yes | Yes | Yes |
| Cross-tab overlapping-scope serialization | Yes | Yes | Yes |
| BroadcastChannel for notifications | Yes | Yes | Yes (15.4+) |
| bfcache-safe subscribers (pageshow reconcile) | Yes | Yes | Yes (workaround) |
| WebKit silently drops BroadcastChannel messages to frozen pages. The library reconciles against IDB on pageshow with persisted:true. | |||
| navigator.storage.persist() | Silent heuristic | UI prompt | 17+, heuristic favors installed web apps |
| navigator.storage.estimate() | Yes | Yes | Yes (rounded) |
| Private browsing | Ephemeral (Incognito) | Ephemeral (Private Windows, since FF 115) | Ephemeral |
| 7-day inactivity eviction | No (LRU under pressure only) | No | Yes (ITP) — Home Screen web apps exempt |
| This is the ios-capped evictionRisk value. Prompt users to install as a Home Screen web app. | |||
The known trap by engine
Chromium — durability: "relaxed" improves small-write throughput
on Chromium and matches the semantics this library needs. Storage
Buckets (Chromium 122+) are a proposed 0.2 target.
Firefox — Private Windows use encrypted on-disk IDB since Firefox 115, so writes succeed. Not visible in the Storage inspector. Historical Bugzilla 1193394 (async gap deactivates transactions early at the "meta-stable" state) is why the library never awaits non-IDB promises inside a transaction.
WebKit — the strictest engine on the "no await inside the txn"
rule; the library respects it in every code path. navigator.storage. persist() may return true in a regular Safari tab while ITP still
evicts data after 7 days. The library surfaces this as
evictionRisk: "ios-capped" so the application can prompt the user
to install as a Home Screen web app, where the timer resets on
interaction.
Node
Not supported for reads or writes. The library will not fake persistence
with an in-memory shim — a memory fallback violates the product
promise. Guard createDurable() behind typeof window !== "undefined"
in SSR code.
For unit tests in Node, use fake-indexeddb. That is what the
library's own test suite does; there is nothing special about the setup.