Comparison
How Persist relates to zustand-persist, redux-persist, pinia-persist, and other store persist middlewares.
Relationship to store persist middlewares
zustand-persist, redux-persist, and pinia-persist each wire one store library to storage with a flat options bag. @stainless-code/persist binds to a structural PersistableSource (getState/setState/subscribe), so the same call persists TanStack Store, zustand, Redux, Pinia, or a hand-rolled atom. Three seams — backend (StateStorage), codec (StorageCodec), source (PersistableSource) — make every backend × codec cell a one-line composition. The hydration lifecycle (onHydrate / onFinishHydration / hasHydrated, via HydrationSignal and framework adapters) gates UI flash without coupling to the store’s read path; versioned migrate, crossTab + onCrossTabRemove, and retryWrite cover schema evolution, multi-tab sync, and quota errors.
Comparison with other store persist libraries
Every row is a seam or lifecycle concern — not a roadmap item. @stainless-code/persist treats each as composable; incumbents bake most of them into framework-specific middleware.
| Capability | @stainless-code/persist |
zustand-persist | redux-persist | pinia-persist |
|---|---|---|---|---|
| Store-agnostic (structural source) | ✅ | ❌ | ❌ | ❌ |
| Codec seam (swap serialization) | ✅ | 🟡 | ✅ | 🟡 |
| Storage seam (swap backend) | ✅ | ✅ | ✅ | ✅ |
| Hydration signal (gate UI flash) | ✅ | 🟡 | 🟡 | 🟡 |
| Cross-tab sync | ✅ | ❌ | ❌ | ❌ |
migrate (versioned) |
✅ | ✅ | ✅ | ❌ |
retryWrite (quota shrink-or-give-up) |
✅ | ❌ | ❌ | ❌ |
throttleMs |
✅ | ❌ | ✅ | ❌ |
maxAge / buster expiry |
✅ | ❌ | ❌ | ❌ |
| Schema validation (codec) | ✅ | ❌ | ❌ | ❌ |
| Framework hydration adapters | ✅ | ❌ | ❌ | ❌ |
Legend: ✅ full · 🟡 partial · ❌ none.
Differentiator: store-agnostic PersistableSource, a codec seam that includes schema validation, built-in cross-tab sync, and a hydration signal you can mount in any framework adapter — without rewriting when you swap zustand for TanStack Store or localStorage for IndexedDB.
When to skip Persist
- One store + sync
localStorage+ no migrate / cross-tab / hydrate gate → zustand-persist (or the store’s built-in middleware) is fewer moving parts. - Query/cache durability → that library’s own persist client, not this middleware.
Migrating from an incumbent: Migrating from ….