What is LiveStore?
LiveStore is an event-driven data layer with a built-in sync engine. Its primary use case is building complex, client-side apps — like Linear, Figma, or Notion — that also work offline. Think of LiveStore as a next-generation state management library (like Zustand or Redux) that also persists and distributes state across clients and devices.UX
Synced — real-time updates across devices. Fast — no async loading over the network. Persistent — works offline and survives page refresh.
DX
Principled — event-driven instead of mutable state. Type-safe — fully typed events and queries. Reactive — automatic UI updates when data changes.
AX
Testable — immutable eventlog for tight feedback loops. Debuggable — same events always produce the same state. Evolvable — reset and fork state for experiments.
The core idea: synced events → state → UI
Unlike other sync solutions, LiveStore syncs events — not state. Events are immutable facts that describe what happened (TodoCreated, TodoCompleted). State is derived by replaying those events. Every client reconstructs the same state from the same event history, making sync predictable and debuggable. State changes then trigger reactive UI updates.
Traditional state management uses ephemeral, in-memory state
With traditional state management you dispatch actions that update an in-memory store, and the UI reacts to changes. But that state vanishes when the user refreshes or closes the browser. Add persistence and you need to manage local storage as a secondary database. Add sync and you’re dealing with conflict resolution, offline queues, and backend integration. LiveStore handles all of this through one unified pattern: event sourcing. Instead of mutating state directly, you commit events that describe what happened. These events are persisted to an eventlog (like a git history) and automatically materialized into a local SQLite database that your UI queries reactively.While most apps use SQLite as the data store for persistence, LiveStore is flexible enough to materialize state into other targets as well (for example, file systems).
Comparison with traditional state management
If you’ve used Redux, committing events will feel familiar: events are like actions, materializers are like reducers, and the SQLite state is like your store. But there are key differences:| Redux | LiveStore | |
|---|---|---|
| Write model | Actions dispatch → reducers update in-memory state | Events commit → materializers update SQLite |
| Persistence | State lost on refresh | Events persisted locally |
| Sync | Requires external setup | Built-in via eventlog |
| Query model | Fixed state shape | Query any shape with SQL |
| Bundle size | Small | Larger (includes SQLite) |
A practical example
Every LiveStore app starts with a schema made of three parts:- Events — describe what can happen in your app
- State — defines how data is stored (SQLite tables)
- Materializers — map events to state changes
Define your schema
schema.ts
Use it in React
LiveStore includes integrations for all major frontend frameworks. ThequeryDb function creates a reactive query that updates automatically when its data changes:
TodoApp.tsx
Add sync via Cloudflare
When you’re ready to sync state across clients, configure a sync backend in your worker:worker.ts
Why events?
Committing events rather than mutating state directly gives you several advantages:Events capture intent, not just outcome
Events capture intent, not just outcome
When you mutate state directly (
todo.completed = true), you lose the why. Events like TodoCompleted preserve the user’s intent, which matters for debugging, analytics, undo/redo, and activity feeds.Events decouple what happened from how it's stored
Events decouple what happened from how it's stored
Your state shape can evolve independently of your event history. Need a new denormalized table for performance? Add a materializer — no data migration required.
Events make sync tractable
Events make sync tractable
Syncing mutable state across devices is hard (which field wins?). Syncing an append-only event log is simpler: you’re merging histories, not reconciling conflicting states.
Events give you a full audit trail
Events give you a full audit trail
Every change is recorded. You can replay events to reconstruct any point in time, debug state transitions, or implement time-travel debugging via the devtools.
When LiveStore fits
Good fit
Productivity apps, collaborative tools, offline-first apps, apps with complex local state needing SQL queries, cross-platform apps (web, mobile, desktop, server).
Not a good fit
Data that must live on an existing server database, traditional client-server apps without offline needs, unbounded data that won’t fit in client memory.
Next steps
How LiveStore works
Deep dive into the architecture: event flow, leader thread, sync, and conflict resolution
Concepts
Reference for every LiveStore concept: adapters, sessions, schemas, reactivity, and more
When to use LiveStore
Detailed evaluation guide and comparison with alternatives
Quick start (React)
Set up a React app with LiveStore in minutes