Sync Guidelines
Core Principles
- •Server is source of truth - IndexedDB is a cache
- •All ops kept forever - no pruning, enables full audit trail
- •Shallow snapshots for fast start - performance only, not compaction
- •Encryption at rest - server sees encrypted blobs + plaintext version metadata
Persistence Flow
| Event | IndexedDB | Server |
|---|---|---|
| Local change | Immediate | Throttled (~2s) |
| Tab hidden/close | Immediate | Flush pending |
| Cold start | Load snapshot → usable | Background sync |
Critical Rules
- •IndexedDB writes immediate - crash safety
- •Server pushes throttled - use
lodash-esthrottle, ~2s - •Encrypt before storage - never plaintext in IndexedDB or server
- •Version vector plaintext - enables server filtering without decryption
- •
has_unpushedflag critical - server must send ops (not snapshot) if client has local changes - •Flush on visibility change - don't lose data on tab switch
Key Details
- •loro-mirror auto-commits on
setState()- no manual debouncing - •
subscribeLocalUpdatesfires after each commit with binary update - •Snapshot refresh: ops > 1000 OR bytes > 1MB (not time-based)
Conflict Resolution
Loro handles automatically: last-write-wins per field, set union for arrays.
UI States
- •Saved - all pushed
- •Saving... - pending in buffer
- •Offline - can't reach server