You know, Local-First is not Offline-First

If you have ever read the book The Pragmatic Programmer, particularly the second edition, you’ll remember that the authors have outlined that about one-third of the book was rewritten to update the references, code examples, and introduce new technical nuances and practices compared to the first edition. This update was necessary because the field of software development is so broad, and every day brings something new with its own dynamics. One concept can mean something different in various domains, and since we can’t standardize everything, it becomes much harder to fully grasp the idea of ‘what is what’ and ‘why it is named like that.’ A similar challenge arises when people talk about Local-First software and Offline-First software.

Before moving ahead, let’s clarify one major distinction between the two that will help you to resonate down the article: In Local-First software, you own your data, but not in Offline-First software.

The ability to function without an internet connection is central to both local-first and offline-first apps. In an offline-first app, data is stored locally when there is no internet connection, but it gets synced up as soon as the internet connection is restored. After syncing, the locally stored data is removed since the server then becomes the primary data source. In contrast, for local-first apps, data is always stored locally—such as in a browser’s local storage—and is continuously synced with the server whenever changes are made, either locally or remotely. The local data is never wiped out, and all operational logic resides within the client application code. This setup allows local-first apps to execute operations faster than offline-first apps due to fewer server round trips.

In an offline-first app, syncing happens only when there is local data to sync. With local-first apps, however, syncing occurs at frequent, small intervals to keep data updated and consistent, often using specialized data structures like CRDTs (Conflict-free Replicated Data Types). In offline-first apps, while data is stored locally, the server remains the primary data source. For local-first apps, however, the primary data source is the local storage. Actions don’t require active network calls to update data on the remote server; instead, changes are made locally. A sync engine then handles local and remote changes, resolves conflicts, and updates both the local storage and remote server in the background, often on a separate thread to avoid interrupting the primary thread.

Having control over data stored on your local machine offers benefits beyond reducing network overhead. Though both local-first and offline-first apps can store data locally, data management and ownership differ. In offline-first or cloud-based apps, servers manage and own the data. However, with local-first apps, all data resides on the user’s local machine, making the user the practical owner. Ideally, it should have always been this way, but with cloud apps, the data you create is owned by the service providers, not you. They could restrict access, ask you to leave, or even shut down the app altogether, causing you to lose the data you provided simply because it’s not under your control. With local-first apps, even when a remote server exists to sync data, local storage remains the primary data source, providing complete data ownership, no downtime or data loss, and always-available services.

Data persistence in local-first apps is highly efficient and more durable than in offline or cloud apps, optimizing the syncing operation and maintaining overall app performance. This ensures the app remains accessible as long as there’s a local copy of the data, even if the software itself is no longer available for use.

That said, the concept of local-first is still evolving, though some great real-world applications like Linear and CouchDB already use it. It represents a significant shift in how we build and deploy apps. The idea of a sync engine is quite complex and varies depending on use cases, but it’s certainly something that could shape a new approach to app development moving forward.