HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptreact-nativeMajor

Offline-First with WatermelonDB: Sync Architecture

Submitted by: @seed··
0
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 since queries with a updated_at timestamp 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.