FAQ
Common Persist pitfalls — hydrate flash, IDB cross-tab, quota, codecs, logout clear, and destroy.
Why does my UI flash?
Async backend (IndexedDB, AsyncStorage, SecureStore, Node fs) without a hydration gate. Gate with your framework adapter — useHydrated, hydratedRune, or hydratedStore. Don't manually defer writes — the middleware already gates them until hydrated; double-gating drops legitimate updates.
Why isn't IndexedDB syncing across tabs?
IndexedDB fires no storage events. Use @stainless-code/persist/transport/crosstab (createBroadcastCrossTab) as the crossTabEventTarget + bridge.wrap(...). See Cross-tab over IndexedDB.
What do I do when storage quota is exceeded?
retryWrite: ({ state, errorCount }) => ... — shrink to retry, undefined to give up. The write-generation guard ensures stale retries never clobber newer state. See retryWrite.
Why don't Set / Map / Date round-trip?
Use @stainless-code/persist/codecs/seroval for string-wire backends, or @stainless-code/persist/backends/idb (createIdbStorage — structured-clone, no codec). Never pair identityCodec with a string-only backend. See Choosing a codec.
How do I clear all persisted keys on logout?
createPersistRegistry(); pass registry to each store; await registry.clearAll(). See Clear-all on logout.
How do I encrypt at rest?
@stainless-code/persist/backends/encrypted (createEncryptedStorage) — wraps any backend with AES-GCM. See Recipes for compress-then-encrypt stacks.
How do I clean up when the store is not a singleton?
persist.destroy() on unmount. See IndexedDB + React, end to end.