SSSync documentation (very, very WIP)
In 2026, the sync space has a bunch of interesting libraries and services, some that provide live subscriptions atop a commodity database like Postgres (powersync.com, [zerosync.dev], electric-sql.com) or a proprietary solution (instantdb.com, convex.dev), and others based on event sourcing (livestore.dev). The tradeoffs here are simple enough:
- Live subscriptions, no matter how efficiently implemented, have an overhead in infrastructure costs, and require you to pre-register your queries on the server. Consistency and flexibility are gained, but at some cost. Some of these solutions also fail to provide true offline-first usage.
- Event sourcing is incredibly simple and efficient (it can even use Git as a storage layer), but lacks a single materialized database to query directly. And thus requires sending the full event log for each resource. It is also very hard to split up an event log once it’s defined. Simplicity, at the cost of flexibility.
What SSSync aims to achieve is the following:
- offline-first usage
- partial data loading
- simple infrastructure (serverless server + any database + web client), that can be run cheaply
- pleasant DX (prototyping, dev tools, simple model), with the basics taken care of
- centralised schema, migrations, relationships, etc.
It does so at the cost of not being as easy to use as the other options (the more complex the app, the more work involved), since you have to implement the server part of things yourself. But it does handle the hard parts of sync on the client, and provides a lovely UI development experience.
It is inspired in part by the architecure of the Linear Sync Engine, generalised to a client-side library and recommended server-side implementation. It is informed by the hundreds of hours I have spent on sync problems myself, dealing with the various ways it can (and does) go wrong.
In some ways, it is also a bet on “replacing infrastructure with code” for apps that can afford to do so. This might be a minority, since anything that deals with real-world resources should not use a local-first approach. But for this minority, wouldn’t it be nice to benefit from local-first?
API
My desired API for SSSync.
Setting things up…
const ssync = new SSSync("id", {
store,
loaders,
})
Usage…
const books = sssync.query.books.where("pageCount", ">=", 4);
const booksFetch = sssync.persist('/user/books')
const libraryData = sssync.temporary('/api/library/:id', {refreshSeconds: 3})
const newBook = sssync.execute.createBook('id-2313', 'Cool Title')
FAQ
When should I not use this?
If you’re building anything that must maintain strong consistency, i.e. you’re dealing with real world resources that are scarce. You do not want people to make e-commerce purchases while offline, or try to make a bank transaction that says “complete” but may or may not have actually synced to the server.
Why offline-first?
Web. Poor network. PWAs exist.
Why stateless?
Simple, not easy. Realtime is…not simple. And often (in the author’s opinion) unnecessary, perhaps even undesirable.
Will this scale to [insert large number here] users?
It depends on how well you set things up to do so. There are no fundamental bottlenecks to keeping things performant as your storage needs increase — at worst, SSSync is much more efficient than a regular web app that makes full API requests on each payload.
There is no special magic server that might run out of memory, or special database with storage constraints. You can build whatever backend you like, as long as it satisfies the protocol.
Is this approach local-first?
The defintions of that term are very muddled at the moment (read more), but we think the the seven original principles of the local-first paper are the correct banchmark to use.
- No spinners: your work at your fingertips
- Your work is not trapped on one device
- The network is optional
- Seamless collaboration with your colleagues
- The Long Now
- Security and privacy by default
- You retain ultimate ownership and control
SSSync itself doesn’t make your app full local-first, it starts out as a subset and gives the developer the ability to make it fully so if they desire.
We’re as offline-first as can be, so that satisfies points 1 and 3, and we’re a protocol for connecting to a server that syncs updates and satisfies queries, which accomplishes 2 and 4 once implemented correctly.
Points 5, 6, and 7 are as true as you make them.
- Privacy and security: You can encrypt all user data and still continue using our sync protocol. Our library doesn’t care about what you sync as long as it has unique IDs for each object.
- The Long Now: If you build a desktop app instead of web one, people can keep using it even if someone stops paying for the server. The data is usually stored as very readable JSON or SQLite.
- Ownership and control: Users can be “able to copy and modify data in any way” by appending to the event log, through any means that the developer chooses to expose that functionality. As long as they use events from the existing list, the application can process an sync them perfectly fine.