DurableStash

Keep Phoenix LiveView state alive across reconnects, crashes, and redeploys.

A LiveView's assigns live in memory and vanish when the socket drops, the process crashes, or you deploy. DurableStash saves the assigns you pick to object storage and restores them the next time the LiveView mounts. The saved copy belongs to the browser session, so every LiveView the user opens shares it. Under the hood it plugs into LiveStash and stores state through DurableServer.

State survives:

State dies with the browser session: cleared cookies, another browser, or TTL expiry mean defaults.

Usage

defmodule MyAppWeb.SomeLive do
use MyAppWeb, :live_view
use LiveStash, adapter: DurableStash, stored_keys: [:count, :username]
def mount(_params, _session, socket) do
socket = assign(socket, count: 0, username: nil)
{_status, socket} = LiveStash.recover_state(socket)
{:ok, socket}
end
def handle_event("increment", _params, socket) do
socket = update(socket, :count, &(&1 + 1))
{:noreply, LiveStash.stash(socket)}
end
end

Scopes

Not all state wants the same recovery policy, so each stored key declares one:

use LiveStash, adapter: DurableStash,
stored_keys: [
theme: :session, # recover on every mount (the default for bare atoms)
draft: :reconnect # recover only on rejoins; cleared on fresh navigation
]

See the DurableStash moduledoc for setup (adapter registration, backend config, the ensure_session_id plug) and all options (:vsn, :migrate, :secret).

How it works

DurableStash.TestBackend ships with the package: a faithful in-memory DurableServer.StorageBackend (including etag CAS) for tests and make run style development without S3 credentials.

Installation

def deps do
[
{:durable_stash, "~> 0.1.0"}
]
end

Credits

DurableStash stands on two lineages: