{
  "slug": "store/sync",
  "title": "Sync & Conflict Resolution",
  "description": "Configure automatic sync strategies and conflict resolution for Store stores.",
  "url": "https://cuitty.com/docs/store/sync",
  "markdown_url": "https://cuitty.com/docs/store/sync.md",
  "json_url": "https://cuitty.com/docs/store/sync.json",
  "frontmatter": {
    "title": "Sync & Conflict Resolution",
    "description": "Configure automatic sync strategies and conflict resolution for Store stores.",
    "order": 3,
    "section": "Store",
    "updatedAt": "2026-05-12"
  },
  "headings": [
    {
      "depth": 1,
      "slug": "sync--conflict-resolution",
      "text": "Sync & Conflict Resolution"
    },
    {
      "depth": 2,
      "slug": "how-sync-works",
      "text": "How sync works"
    },
    {
      "depth": 2,
      "slug": "configuration",
      "text": "Configuration"
    },
    {
      "depth": 3,
      "slug": "options",
      "text": "Options"
    },
    {
      "depth": 2,
      "slug": "strategies",
      "text": "Strategies"
    },
    {
      "depth": 3,
      "slug": "last-write-wins-lww",
      "text": "Last-write-wins (LWW)"
    },
    {
      "depth": 3,
      "slug": "crdts",
      "text": "CRDTs"
    },
    {
      "depth": 3,
      "slug": "custom-merge",
      "text": "Custom merge"
    },
    {
      "depth": 2,
      "slug": "conflict-resolution-callbacks",
      "text": "Conflict resolution callbacks"
    },
    {
      "depth": 2,
      "slug": "offline-first-behavior",
      "text": "Offline-first behavior"
    },
    {
      "depth": 2,
      "slug": "monitoring-sync-status",
      "text": "Monitoring sync status"
    }
  ],
  "body_markdown": "# Sync & Conflict Resolution\n\n## How sync works\n\nStore is offline-first. Writes go to the local store immediately and never block on network. A background sync queue pushes changes to the remote and pulls remote changes back.\n\n```\nlocal write --> local store --> sync queue --> remote\n                                   ^\n                                   |\n                         pull remote changes\n```\n\n## Configuration\n\n```ts\nimport { createStore } from \"@cuitty/store\";\n\nconst store = await createStore({\n  name: \"my-app\",\n  adapter: \"sqlite\",\n  path: \"./data/my-app.db\",\n  sync: {\n    remote: \"postgres\",\n    strategy: \"last-write-wins\",\n    interval: 5000, // sync every 5 seconds (default: 10000)\n  },\n});\n```\n\n### Options\n\n| Option       | Type     | Default            | Description                         |\n| ------------ | -------- | ------------------ | ----------------------------------- |\n| `remote`     | `string` | --                 | Remote adapter type or connection   |\n| `strategy`   | `string` | `\"last-write-wins\"`| Conflict resolution strategy        |\n| `interval`   | `number` | `10000`            | Sync interval in milliseconds       |\n\n## Strategies\n\n### Last-write-wins (LWW)\n\nThe simplest strategy. Each record carries a timestamp; the most recent write wins on conflict.\n\n```ts\nsync: {\n  remote: \"postgres\",\n  strategy: \"last-write-wins\",\n}\n```\n\nGood for settings, preferences, and data where overwrites are acceptable.\n\n### CRDTs\n\nConflict-free replicated data types that merge automatically without data loss. Best for collaborative data.\n\n```ts\nsync: {\n  remote: \"postgres\",\n  strategy: \"crdt\",\n}\n```\n\nStore uses operation-based CRDTs under the hood. Counters, sets, and maps merge deterministically across peers.\n\n### Custom merge\n\nSupply a function that receives both versions and returns the resolved value.\n\n```ts\nsync: {\n  remote: \"postgres\",\n  strategy: \"custom\",\n  merge(local, remote) {\n    // Example: keep the record with more fields\n    const localKeys = Object.keys(local.value);\n    const remoteKeys = Object.keys(remote.value);\n    return localKeys.length >= remoteKeys.length ? local : remote;\n  },\n}\n```\n\n## Conflict resolution callbacks\n\nRegister a callback to handle conflicts interactively or log them.\n\n```ts\nstore.events.on(\"conflict\", (event) => {\n  console.log(`Conflict on key: ${event.key}`);\n  console.log(\"Local:\", event.local);\n  console.log(\"Remote:\", event.remote);\n  console.log(\"Resolved:\", event.resolved);\n});\n```\n\n## Offline-first behavior\n\nWhen the device is offline, Store continues to accept reads and writes against the local store. Changes accumulate in the sync queue and flush automatically when connectivity returns.\n\nThe sync queue is persisted to disk, so pending changes survive app restarts.\n\n## Monitoring sync status\n\n```ts\nconst status = store.sync.status();\n// { state: \"synced\" | \"syncing\" | \"offline\", pending: number, lastSync: Date }\n\nstore.events.on(\"sync\", (event) => {\n  console.log(`Synced ${event.pushed} up, ${event.pulled} down`);\n});\n```",
  "links_out": []
}