NOTE: LiveStore is still in beta and releases can include breaking changes.
See
state of the project
for more info. LiveStore is following a semver-like release strategy where
breaking changes are released in minor versions before the 1.0 release.
0.4.0
For v0.4.0 features, see the development documentation at dev.docs.livestore.dev which includes the latest documentation.
Installing v0.4.0 dev release: Use the dev tag to install the latest development version. Make sure all LiveStore packages use the same version:
LiveStore now runs natively on Cloudflare Workers through the new @livestore/adapter-cloudflare package. This adapter leverages Durable Objects for stateful coordination and D1 for persistence, enabling globally distributed applications with local-first performance characteristics.
The adapter supports:
Stateful Durable Objects for managing LiveStore instances
D1 database integration for event persistence
Hibernatable architecture to minimize compute costs
Direct integration with the Cloudflare sync provider
The @livestore/sync-cf package has been rewritten to provide more reliable and efficient synchronization. The new implementation supports three transport protocols, each optimized for different deployment scenarios:
WebSocket transport: Bidirectional real-time communication with automatic reconnection
HTTP transport: Request-response based sync with polling for environments that don’t support WebSockets
Durable Object RPC transport: Direct communication between Durable Objects, eliminating network overhead
The @livestore/wa-sqlite package now follows LiveStore’s versioning scheme instead of its independent versioning. This ensures version consistency across all LiveStore packages.
Migration:
Terminal window
# Before: wa-sqlite had independent versioning
pnpmaddwa-sqlite@1.0.5
# After: wa-sqlite follows LiveStore versioning
pnpmadd@livestore/wa-sqlite@dev
This change affects projects that directly depend on wa-sqlite. Most users rely on it indirectly through LiveStore adapters and don’t need to change anything.
Bug Fixes
Fix client document schema migration with optimistic decoding (#588)
Fix query builder method order to preserve where clauses (#586)
Fix race condition in schema migration initialization (#566)
Fix handling of optional fields without defaults in client documents (#487)
Fix Symbol values in QueryCache key generation
Fix TypeScript build issues and examples restructuring
Fix in-memory SQLite database connection handling in Expo adapter
Fix OPFS file pool capacity exhaustion from old state databases (#569)
Comprehensive sync provider test suite with property-based testing
Node.js sync test infrastructure with Wrangler dev server integration (#594)
Parallel CI test execution reducing test time significantly (#523)
Development Tooling
Migration from ESLint to Biome for improved performance (#447)
Automated dependency management with Renovate
Pre-commit hooks via Husky (#522)
Comprehensive dependency update script (#516)
Add GitHub issue templates to improve issue quality (#602)
wa-sqlite Integration
The wa-sqlite WebAssembly SQLite implementation has been integrated directly into the LiveStore monorepo as a git subtree under packages/@livestore/wa-sqlite. This change provides several benefits:
Direct control over SQLite builds and customizations for LiveStore’s needs
Simplified dependency management and version alignment
Ability to apply LiveStore-specific patches and optimizations
Reduced external dependency risks and improved build reproducibility
Key changes:
Integrated wa-sqlite as git subtree, replacing external npm dependency (#582)
Ported build scripts and test infrastructure to LiveStore monorepo (#572)
Updated to SQLite 3.50.4 with LiveStore-optimized configuration (#581)
Fixed test setup issues and improved reliability (#583)
This integration lays the foundation for future SQLite optimizations specific to LiveStore’s event-sourcing and sync requirements.
Experimental Features
LiveStore CLI for project scaffolding (experimental preview, not production-ready)
Note: Currently uses the @livestore/sqlite-wasm build but the plan is to
move to a native SQLite build in the future to improve performance and
reduce bundle size.
Still lacks a few devtools-related flows (e.g. graceful import/reset)
Breaking @livestore/adapter-web: Renamed makeAdapter to
makePersistedAdapter
Breaking @livestore/adapter-expo: Renamed makeAdapter to
makePersistedAdapter
Breaking: Renamed localOnly to clientOnly in table/mutation definitions.
Breaking: Renamed makeBackend to backend in sync options.
Breaking @livestore/react: useClientDocument now only works with for
tables with client-only derived mutations.
Breaking: Instead of calling query$.run() / query$.runAndDestroy(), please
use store.query(query$) instead.
Breaking: Removed store.__execute from Store.
Breaking: Removed globalReactivityGraph and explicit passing of
reactivityGraph to queries.
Breaking: Removed persisted option from store.commit. This will be
superceded by
eventlog compaction in
the future.
Breaking: The new syncing implementation required some changes to the storage
format. The liveStoreStorageFormatVersion has been bumped to 3 which will
create new database files.
Breaking: Moved queryGraphQL to @livestore/graphql and thus removing
graphql from peer dependencies of @livestore/livestore.
Moved dev helper methods from e.g. store.__devDownloadDb() to
store._dev.downloadDb()
Breaking @livestore/sync-cf: Renamed makeWsSync to makeWsSync
Notable improvements & fixes
Added support for write queries in the query builder
Introduced @livestore/peer-deps package to simplify dependency management
for Livestore packages if you don’t want to manually install all the peer
dependencies yourself.
Improved documentation (still a lot of work to do
here)
Shows a browser dialog when trying to close a tab/window with unsaved changes
The SQLite leader database now uses the WAL mode to improve performance and
reliability. (Thanks @IGassmann for the
contribution #259.)
Improve Otel tracing integration
Fix: The query builder now correctly handles IN and NOT IN where
operations
Fix: LiveStore crashes when using reserved keywords as a column name (from)
#245
Devtools
Changed devtools path from /_devtools.html to /_livestore
General connection stability improvements
Improved sync view:
See sync heads in real-time
Connect/disconnect button
Improved eventlog view:
Client-only mutations are now highlighted
Added clientId / sessionId columns
Grouped slow queries and live queries under new queries tab
Added SQLite query playground
Fix: Data browser now more clearly highlights selected table #239
Examples
Reworked the Linearlite React example. (Thanks
@lukaswiesehan for the contribution #248.)
Adjusted mutation names to use past-tense
Added Otel to todomvc and todomvc-sync-cf example
Internal changes
Embraced git-style push/pull semantics to sync mutations across the system
Added node syncing integration tests
Got rid of the coordinator abstraction in favour of a clear separation between
leader and client sessions
Renamed from EventId.local to EventSequenceNumber.client
Added @livestore/sqlite-wasm package which wraps @livestore/wa-sqlite and
exposes web and Node.js compatible VFS implementations
New devtools protocol via webmesh
Should improve reliability of devtools connection (particularly during app
reloads)
Large refactoring to share more code between adapters
Renamed SynchronousDatabase to SqliteDb
Upgrade to TypeScript 5.8
Upgraded dependencies
Now supports React 19
effect (needs to be 3.15.2 or higher)
@livestore/wa-sqlite (needs to be 1.0.5)
Still todo:
Release
Write blog post
Prepare X/Bluesky thread
After release:
Refactor: Get rid of sql-queries module
API improvement: Get rid of queryDb by exposing live queries directly on the
query builder / state primitives
Optimization: Bring back rehydrating via in-memory database (requires both app
and mutation db to be in-memory)
Web adapter:
Bug:
NotReadableError: The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.
Refactor shared-worker
Make it optional (for Android support)
Make it store-agnostic (so it’s reused across store instances)
Remove extra broadcast channel for session info in @livestore/adapter-web
Bug fix + testing: SQLite rollback error:
RuntimeError: null function or function signature mismatch, "note": "Failed calling makeChangeset.apply
(needs repro info, probably requires property testing)
Syncing:
introduce a way to know when an event is confirmed by the sync backend
when no sync backend is configured, the leader sync state should not keep
pending events in memory
Testing: Improve sync testing (prop testing): introduce arbitrary latency
for any kind of async step (~ chaos testing)
More graceful handling when receiving a event that doesn’t exist in the
local schema
This can happen if a new app version with a new schema and an old client
with the old schema tries to sync
2 solution paths:
Render “upgrade app” screen
Go offline until user upgrades the app
Clients should detect and gracefully handle when a sync backend resets its
eventlog (e.g. during debugging)
possibly introduce a eventlog id in the global sync metadata
@livestore/sync-cf:
Opening the snyc HTTP endpoint in the browser should provide a helpful
message
use http for initial pull while WS connection is established
Adjust networking protocol to embrace a “walk” flow similar to how
ElectricSQL’s protocol works. i.e. instead of doing 1 pull-req and getting
n pull-res back, we will adjust this to be 1:1 at the expense of slightly
higher round tripping overhead
We will “downgrade” the purpose of the remaining field to be only used
for UX purposes but not for correctness purposes. For correctness we
will only stop pull-walking when we get an empty array back.
Only use DO for write operations and pokes, use a separate way for
pull-reqs
Bring back “broadcast” pull res terminology
@livestore/sync-electric:
fix: connectivity state + offline handling
implement sync payload
Expo adapter: Fix memory leak in certain cases (needs repro info)
Refactor/improve event sequence number implementation
Current pain points/suboptimalities:
syncstate.ts: branching for global/client-only events
Get rid of leaderMergeCounterTable in favour of client-only merge
generation
Idea: Embed merge generation in the client-only event sequence number
Implementation detail: New event id strategy (uses a global event id integer
sequence number and each event also keeps a reference to its parent event
id)
React integration
Breaking: The React integration has been moved into a new separate package:
@livestore/react (before: @livestore/livestore/react)
Breaking: Renamed useTemporaryQuery to useScopedQuery
Web adapter
Devtools address is now automatically logged during development making
connecting easier.