# Persisted state lifecycle

Persistence adds a storage read and write around a Zustand store: the middleware saves selected state when it changes, then hydrates the store from saved values during initialization.

## How state moves through persistence

[`persist`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand-middleware#persist) wraps the store's state creator. On initialization, it reads the item identified by `name`, checks its version, optionally migrates it, and merges the stored state with the store's current state. When the store changes, it applies `partialize` and writes that state and the version to storage.

```mermaid
flowchart LR
  A["Initial state creator"] --> B["persist reads storage by name"]
  B --> C{"Stored version matches?"}
  C -->|"No; migrate is configured"| D["migrate stored state"]
  C -->|"Yes, or no stored value"| E["Stored state (possibly absent)"]
  D --> F["merge with current state"]
  E --> F
  F --> G["Hydrated store"]
  G --> H["State update"]
  H --> I["partialize, then write to storage"]
```

The stored value has a `state` and an optional `version` field ([`StorageValue`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand-middleware#storagevalue)). The default storage uses JSON and `localStorage`; the default merge is shallow, with stored top-level fields taking precedence over the current state's fields. If no stored value exists, the current state remains in place.

## Combining and evolving stored state

- The default `merge` is shallow. If you persist a nested object but omit some of its fields, the stored nested object replaces the current nested object at that top-level key. Provide a custom `merge` when rehydration must preserve or combine nested fields.
- Use `version` and `migrate` when a change makes stored data incompatible with the current state shape. A version mismatch without a migration leaves the stored value unused; a migration returns the state for the current version.
- `skipHydration` prevents the initial automatic hydration. This lets an application control when to call `rehydrate()`, such as in a server-rendered application.
- `onRehydrateStorage` provides a callback before hydration and an optional callback after hydration or an error.

For the storage setup and partial-persistence examples, see [Persist state to storage](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/persist-state-to-storage).
