Skip to content

Offline Outbox & Optimistic Writes

src/lib/offline/db.ts defines the Dexie (IndexedDB) database — the sole client-side store (constitution §7.14.1). It holds a read cache of the user’s data plus the persistent mutation outbox. It never stores auth tokens, credentials, or secrets (§7.14.5).

  • The outbox table (OutboxEntry) queues mutations made locally, indexed by createdAt and entityId (for dependency lookups). The Dexie schema is versioned (v1…v8+) as read models were added per feature.
  • Each entry carries a stable Idempotency-Key so replays are deduplicated server-side (the idempotencyKeys D1 table) — replaying the outbox is safe and idempotent (constitution §7.14.3).
  • buildRequest(entry) (in sync-core.ts) turns an outbox entry into the HTTP request the replay sends.

src/lib/offline/sync.ts exposes the user-facing mutations (createList, renameList, deleteList, moveList, duplicateList, createGroup, deleteGroup, moveGroup, …). Each:

  1. applies the change to the Dexie cache and shows it immediately (optimistic);
  2. enqueues an outbox entry;
  3. replays to the server when online, where it is reconciled into D1 (the source of truth).

When offline, writes queue and replay on reconnect; there is no on-device primary database and no sync engine — the client is a cache plus outbox (Product Brief §1.1).

Related: Sync-Core Reconcilers (the read/fold side), DB Schema & Notify-Affected (the server tables + idempotency).