patterntypescriptreact-nativeMajor
Offline-First with WatermelonDB: Sync Architecture
Viewed 0 times
WatermelonDBoffline-firstSQLitesyncconflict resolutionlocal databaselast-write-wins
Problem
Apps that store data only in remote APIs fail completely without internet. Building offline-first requires a local database with a sync protocol that handles conflicts.
Solution
Use WatermelonDB (built on SQLite) for local data. Implement the sync protocol:
synchronize() from @nozbe/watermelondb/sync with pullChanges (fetch server diff since last pulled_at) and pushChanges (send local changes). The framework handles conflict resolution using a last-write-wins strategy by default.Why
WatermelonDB is lazy — it only loads records that are observed. It uses native SQLite via JSI, making queries synchronous and fast. The sync protocol is designed for the React Native offline-first use case, unlike full ORM solutions that assume constant connectivity.
Gotchas
- WatermelonDB models must be defined with a schema — schema migrations are manual
- The sync protocol requires server-side support for
changes sincequeries with aupdated_attimestamp index - Deleted records must use soft deletes (
_deleted: true) — hard deletes break sync - WatermelonDB does not work in Expo Go (requires native module) — use a dev build
Code Snippets
WatermelonDB sync implementation
import { synchronize } from '@nozbe/watermelondb/sync';
import { database } from './database';
async function syncDatabase() {
await synchronize({
database,
pullChanges: async ({ lastPulledAt, schemaVersion, migration }) => {
const { data } = await api.pull({ lastPulledAt, schemaVersion, migration });
return data; // { changes, timestamp }
},
pushChanges: async ({ changes, lastPulledAt }) => {
await api.push({ changes, lastPulledAt });
},
migrationsEnabledAtVersion: 1,
});
}Revisions (0)
No revisions yet.