Saved app state is off by default. It needs the
enable-data-app-state feature flag, which Lightdash support turns on for Cloud organizations on request.useAppState(key, default, { scope: 'url' | 'user' | 'shared' }). See Link state and saved state for why link state and storage are separate, and how one control can use both.
Apps run in a sandboxed frame with no access to browser storage such as localStorage, so values an app keeps only in memory reset when the page reloads. Saved app state is how an app remembers them.
User storage
User storage keeps values for each person separately. It suits anything a viewer sets up for themselves, like filter selections, the active tab, or display settings. Set the app up the way you want it, and it opens in that state when you come back. Other viewers don’t see your choices. There is no setting to turn user storage on for an app. The agent uses it by default for inputs that make sense to remember, such as filters and settings. If you don’t want something remembered, tell the agent when you build or iterate on the app.Shared storage
Shared storage holds values that everyone using the app can see and edit. It suits things people collaborate on, like comment threads, annotations, targets, or a simple ticket tracker. Lightdash keeps a history of who changed each shared value. The agent doesn’t use shared storage by default. Ask for it in your prompt and say what should be shared, for example “let the team leave comments on each region, visible to everyone”. Shared storage also powers saved AI commentary: ask for “AI commentary that is saved and shared between viewers” and the app generates a takeaway once per selection, saves it for every later viewer, and lets anyone edit the text. This needs AI analysis turned on as well. Shared values don’t update live. Other people’s edits appear when the app loads, when you come back to its browser tab, or when you click a refresh control the app provides.Link state and saved state
Link state (theurl scope) says which view you’re looking at. User and shared storage hold data. Storage can’t replace link state, because a link to an app has to reproduce the view of the person who shared it, and storage can’t do that:
- User storage follows the person, not the link. If you save a period of Q3 and send a teammate your link, the app loads their saved period, or the default. The one thing the link has to carry, your current view, is exactly what per-user storage can’t carry.
- Shared storage would change the view for everyone. If view controls were shared, every viewer switching a tab would change what the whole team sees on their next open. Two people looking around at the same time would get version conflicts, and embedded viewers can’t write shared values at all.
- Storage holds one value per key. Link state belongs to a browser tab, so two tabs can show Q3 and year to date side by side, and you can bookmark several views of one app. Two tabs reading the same saved key would overwrite each other.
- Some views have no person behind them. Hand-built deep links, scheduled deliveries, and other headless renders set a specific view when the app renders, with no viewer whose storage could hold it. A delivery has to capture the view that was configured for it.
- Link state works without saved app state. It needs no feature flag, no backend writes, and has no storage limits. It’s the only scope available in organizations without saved app state and in view-only embedded sessions.
useAppState(key, default, { url: true }) in app code). Opening the app from the menu brings back your last choice. Opening a link shows the value in the link, and the link’s value wins until you change the control.
See what an app has saved
People who can manage an app can open its ⋯ menu and select App state. The panel lists every shared key with its size, version, and who last changed it, and when. Select a key to see its version history, with the author, time, and value of each version.

Limits
- Values are JSON, up to 64 KB per key.
- Each app holds up to 200 shared keys, and up to 200 user keys for each person.
- Lightdash keeps the last 1,000 versions of each shared key.