Local-first software is back, and sync engines are doing the heavy lifting

Most of the software we use still treats the server as the only real copy of our data. Your phone and laptop are thin windows into a database somewhere else, and when the connection drops, the window goes blank. The local-first movement argues that this is backwards. The device should hold the working copy, the network should be a way to synchronise it, and the app should keep working when the network disappears.
The idea is not new, but it is finally practical. What changed is not a philosophical shift among developers. It is that sync engines and conflict-free replicated data types (CRDTs) have matured enough to handle the hardest part, which is merging two edits made on two devices without losing either one. If you are building collaborative software in 2026, sync is no longer an infrastructure detail you hand to a backend team. It is a product decision with consequences for your data model, your permissions and your support costs.
The 2019 manifesto and why it took seven years
In 2019, the research group Ink & Switch published an essay titled Local-first software: you own your data, in spite of the cloud. It listed seven ideals: fast response with no spinners, work that survives network loss, collaboration across devices and people, data that outlives the company that made the app, security and privacy by default, and users who control their own files. Almost nobody disagreed with the list. The problem was the implementation cost.
Building a local-first app used to mean writing your own merge logic, your own storage layer and your own replication protocol. Most teams chose the cloud-only path because it was simpler, and users tolerated the spinners. That calculus has changed as libraries like Automerge and Yjs made CRDTs usable in JavaScript, and as sync engines took over the plumbing around them.
What a sync engine actually does
A CRDT is a data structure designed so that replicas can be merged in any order and still converge to the same result, without a central referee. Text, lists and maps can all be modelled this way. A sync engine sits on top and handles the unglamorous work: moving changes between clients and the server, replicating only the subset of data each user is allowed to see, persisting state across restarts, and reconciling with an authoritative database.
Several production apps now run on this pattern. Linear has written publicly about its client-side store, which lets its issue tracker respond instantly while changes sync in the background. Figma's multiplayer editing is another well-known case of many clients editing the same document concurrently. The lesson from these products is that the local copy is what the user interacts with, and the server becomes a coordinator rather than the bottleneck.
Where the model breaks
CRDTs are excellent at merging text edits and sets of items. They are much less helpful when your business rules depend on global invariants. If two people book the last seat on a flight while offline, a merge function cannot decide who gets it without information that only the server has. The same goes for payments, inventory counts that cannot go negative, and anything involving money or legal commitments.
Schema migration is the second problem teams underestimate. When a client that is three months out of date reconnects, it has to understand data written by a newer version, and the newer version has to tolerate data written by an old one. That requires version gates in the client, careful field deprecation and a plan for clients that never update. Storage is the third. A phone has finite space and a battery budget, so you need eviction policies, partial replication and a clear answer to what happens when the local database grows past what the device can hold.
A simple decision framework
Before choosing a local-first architecture, ask three questions about each type of data in your product. First, does this data need to work offline or respond in under about 100 milliseconds? Second, do multiple people edit the same object concurrently? Third, would losing access to the vendor make the data unusable to the user?
If the answer to all three is yes, you have a strong case for local-first, such as notes, task managers and design tools. If the answer to the first two is no, a conventional server-backed model is usually cheaper and easier to reason about. Most products end up mixed. Drafts and collaborative content sync locally, while payments, roles and billing stay server-authoritative.
Actionable takeaways
- Classify every entity in your data model as CRDT-merged, server-authoritative or read-only, and write that classification down before writing code.
- Version your schema from day one and add client version checks so that old clients fail gracefully instead of corrupting data.
- Test on low-end Android devices with constrained storage, not only on the latest iPhone.
- Run a one-week offline trial internally. Use airplane mode for normal work and log every place where the app blocks you. Those are your real requirements.
Local-first is not a replacement for the cloud. It is a rebalancing, where the device does more of the work the user cares about and the server does the coordination it is good at. The teams that get this right will ship apps that feel faster and survive bad networks, and the teams that treat sync as an afterthought will keep showing spinners.