Syncing data after network comes back

A user logged 50 actions while offline. Network is back. How to send everything in the right order without losing any of it.

Syncing data after network comes back

Storing actions locally is half the job. The other half is sending them correctly when the network returns. Lots of pitfalls live here.

Syncing data after network comes back
Lifecycle of an offline operation — from tap to server.

Queue structure

  • Each action lives in IndexedDB as a record with: id, type, payload, createdAt, retries, status
  • Status: pending → sending → done or failed
  • Sort by createdAt — send in creation order

When to send

  • Background Sync API — the browser wakes the SW when network returns. As of 2026 only Chrome and Edge support it
  • Online event — `window.addEventListener('online', flush)` — works everywhere, but only catches offline→online transitions
  • Periodic check — try every 30 seconds if there are pending items. Old school, reliable
  • Best — combine all three: Background Sync where supported, online event as fallback, periodic check as a safety net

Retry logic

  • Exponential backoff: 1s, 2s, 4s, 8s — capped at 5 minutes
  • Maximum retries: 5-10. After that, mark as failed and surface in UI
  • Network errors — retry. 4xx responses (401, 403, 404, 422) — do not retry, fail immediately
  • 5xx responses — retry with increased delay

Conflicts

The hardest part. Two users edited the same record offline. Options:

  • Last-write-wins — the latest edit wins. Simple, but data is lost
  • Optimistic locking — each record has a version. Server rejects updates with stale version. UI asks the user to resolve
  • CRDTs — data structures that merge automatically. Hard to implement, but the only real path for collaborative editing

UI

  • Counter badge for unsynced items in a corner of the screen
  • Tap to see the list with retry or delete options
  • If retries exhaust, surface a notification with actions