FrontendPro

125Implement an offline-first data synchronization queue using IndexedDB

hardAbout 75 minutesCodingofflineindexeddbsyncresilience

Problem

A field-sales app must keep working on a train with no signal: every change is applied locally at once and synced when the network returns, even if the tab was closed in between.

Implement createSyncQueue({ store, send, online = true, retryDelay = (attempt) => 1000 * 2 ** attempt }):

  • store is a persistence adapter with async getAll(), put(record) and delete(id). In the browser it is backed by IndexedDB (see the adapter in the solution); in tests it is in memory.
  • send(op) delivers one operation to the server. It rejects with a TypeError for network problems (retryable), or with an error that has a 4xx status for operations the server will never accept.

The queue returns { ready, enqueue(op, { coalesceKey }), flush(), setOnline(online), pending(), failed() }:

  • ready is a promise that resolves after previously stored records are loaded (they survive reloads).
  • enqueue persists { id, op, attempts: 0, status: "pending", coalesceKey } before resolving, then starts a flush if online. If coalesceKey is given and a pending record with the same key exists, replace its op instead of adding a new one (for example, ten edits to the same field send only the latest).
  • flush() sends pending records in order, one at a time. On success, delete the record. On a network error, increase attempts, stop flushing (keeping the order) and retry after retryDelay(attempts - 1). On a 4xx error, mark the record "failed" (a dead letter for the UI to show) and continue with the next one. Only one flush runs at a time; calling flush() during a flush returns the same promise.
  • setOnline(true) starts a flush; setOnline(false) stops starting new sends.
  • pending() and failed() return the records in order.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

solution.jsJavaScript

Press Run or ⌘ Enter to execute your code.

Step-by-step

enqueue writes the record to the store before anything is sent. If the tab closes one millisecond later, the operation is still on disk and will be sent on the next visit.

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 3 code listings, 5 edge cases, 4 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever