We created Linear[1] as local-first product. Back in to 2019 there wasn't much anything available so we created our sync engine. Today we have several thousands companies, from early stage to public companies as paying customers (companies such as Vercel, Replit, Substack, Square..)
Our co-founder did talk about sync engine back in 2020 and recently did updated talk about scaling it [3]. The scaling has definitely taken lot of work and optimizing as datasets for company wide workspace with potentially thousands of users ands object they created can become quite large.
It was off the back of that talk that I was able to finally convince my team to go this route (back in 2019). They'd been trying to handle optimistic updates through Apollo and I was pushing the to make our own sync system over our mobx models to fix the DX.
After watching the talk we picked apart Linear's minified code to better understand the structure and then jumped on a call with Tuomas where he kindly filled any holes in our understanding.
Initially we tried to use IndexDB to give us more of the local-first features by caching between loads, but it was more hassle than it was worth. Instead we settled on live queries using Hasrua (we were a very early user / paying customer). We preload all the data that the user is going to need on app boot and then selectively load large chunks as they open their projects. These are then keeping mobx models up to date.
For mutating data we have a simple transaction system that you wrap around models to update them. It records and sends the mutations and makes sure that outstanding mutations are replayed over model changes locally.
We're not very "local-first" feature-wise; we don't handle conflicts perfectly, really relying on the fact that people are online and receive updates quickly. In practice it works.
Most importantly developers get a familiar graph of objects locally that they can just manipulate and not think about:
I built Mochi [0] from the ground up to be local first. The architecture is built around pouchdb for the local database which syncs to and from a remote couchdb database.
It's been a challenge to implement and in hindsight I wonder if it was even worth it. Unfortunately neither of these technologies are very widely used any more (if they ever were).
I am glad there is a lot of development and research in this area though. I think with the right DX and architecture local first makes a lot more sense than the status quo of continuously fetching everything from a remote database.
I made an open-source Pashto dictionary with a (local-first) word list (with spaced repititon review) that syncs with PouchDb/CouchDb. It's a free dictionary but you pay to get the word list sync. The whole dictionary is designed to be an offline-first SPA so a local-first DB/sync for the word made sense.
Ditto (www.ditto.live) is deployed on all Alaska Airlines, Lufthansa and many other airlines.
It also powers point of sale and kitchen systems at Chick fil A.
The major thing that Ditto is that it can sync without internet using Bluetooth low energy, peer to peer WiFi and Local Area network. It can even do multi-hop.
I am interested in your take on local-first.