Local-first development treats your device as the primary database, syncing to other devices based on your preferences. To figure out what this means for app development, I built one using PowerSync. Check out my demo here.
I have been hearing more and more about local-first data syncing and there is a growing movement around it, like the first annual local-first conference. Local-first can be traced back to a desire to enhance user experience by ensuring faster data access and reducing reliance on constant internet connectivity.
The local-first development paradigm is basically the opposite of the recently prevailing cloud-first paradigm. It involves building apps that treat the user’s local device as the source of truth, so you’re reading and writing data from a local database rather than a central API (in fact, because it’s a more self-contained kind of app, you typically don’t have to worry about writing API functions).
While local-first prioritises the creation of applications and systems that operate primarily on local data, it also strongly supports collaboration and synchronisation across multiple devices and users. To do this you need a sync layer between your app's local database and a central database in the cloud. This enables you to sync data with a backend database even if the network isn’t immediately available.
Why I built NomadNotes
I explored how local-first really works at a recent build day with Make.dev where I got the opportunity to play with PowerSync, a service that keeps a backend Postgres database in sync with on-device SQLite databases embedded in their SDK.
I tested its functionality by building a travel notes app called NomadNotes, using PowerSync, Next.js, and Supabase. This simple app allows users to upload a photo, a description, and a rating of the location or experience, even when they don’t have a network connection. Users can then decide on who they share their travel journals with, which is done once a connection is available again. NomadNotes also includes a private note section where users can capture things like expenses or reminders, which aren’t shared with others.
I learnt a lot about the local-first paradigm by building NomadNotes. Here are my four key lessons:
-
Local-first speeds up the development process
-
Local-first vastly simplifies state management
-
PowerSync helps you seamlessly synchronise data
-
Local-first is particularly useful for front end developers
1. Local-first speeds up the development process
Loading context for a given React component was remarkably intuitive. I simply wrote a SQL query instead of making API calls, transforming the data, and wrestling with JavaScript. PowerSync effectively removes the server layer component, so instead of building API functions and managing data, you speak directly to the database. That sped things up a lot.
Setting up the sharing functionality between NomadNotes users was also much easier. Rather than making an API query to fetch the users, doing a bunch of JavaScript to separate them into lists, and showing the buttons based on different rules, I simply ran an SQL query for each list.
PowerSync also has starter kits available for React, which meant I could copy an example app with the necessary adapter details and get set up quickly.
2. Local-first vastly simplifies state management
State management can get really complicated, especially in frameworks like React where you have a relatively complex tree of states that gets passed in and out of different components. Using PowerSync in a local-first database improved efficiency. Each component had a query that just pulled the data needed. Plus, with uploading and downloading happening automatically, I didn’t need to check if changes propagated to other users.
3. PowerSync helps you seamlessly synchronise data
Local-first development isn’t about ditching the cloud, but rather about keeping a copy of the data close to the user, on their device. This gives you the best of both worlds – syncing to the cloud when it makes sense to do so, while ensuring immediate data access regardless of internet connectivity.
With PowerSync, for example, you can set up sync rules, which determine which buckets of data you download again for each user. You can write a bunch of different queries and rules that give fine control over what gets downloaded from the centralised database on the user side.
4. Local-first is particularly useful for front end developers
I come from a full-stack background and I’ve built a number of apps in React before, so I’m pretty familiar with it. As React is generally a front end framework, I initially found it strange to add SQL to the front end, because those typically go on the back end or a separate API.
Nevertheless, it actually simplified things a lot, with no service layer component to deal with, no API endpoints to build, and no authentication or authorisation to worry about. I just accessed the database directly from the front end, which made development faster and somehow less fragmented.
Dan Davey is a software developer and all-round tech enthusiast, wielding technology to optimise human well-being. He is currently interested in AI/human collaboration, specifically in well-being and creativity.