Skip to content

Design a Reactive Database (Live Queries), stage 8 of 9: break it

Back from the tunnel

The connection is back. Mutations carry a client-generated ID. The server can run queries at its current timestamp.

System so far· 7 parts
123456789CLIENTWeb andmobile appsSERVICESync serversSERVICEFunction runnersDATABASEVersioned storeSERVICECommitterSERVICESubscriptiontrackerCACHEResult cache

Select a component to see what it is responsible for and which state it owns.

  1. 1Web and mobile apps → Sync servers: Subscribe and mutate
  2. 2Sync servers → Function runners: Run a function
  3. 3Function runners → Versioned store: Read at a snapshot
  4. 4Function runners → Committer: Writes plus read set
  5. 5Committer → Versioned store: Append in timestamp order
  6. 6Versioned store → Subscription tracker: Committed writes, in order
  7. 7Subscription tracker → Sync servers: These subscriptions changed
  8. 8Sync servers → Web and mobile apps: New results
  9. 9Function runners → Result cache: Reuse identical runs
  • Request / response
  • Asynchronous
  • Server push

What you need to know

0 of 1 checks done
  1. An optimistic UI shows a change immediately, before the server confirms it, and queues it while offline. On reconnect, three rules keep that safe:

    • Idempotent mutations: each carries a client-generated ID, so the server can skip any it already committed.
    • One timestamp: re-subscribed queries are answered at a single moment, including the replayed mutations.
    • Server results win: the client drops optimistic changes that the server's results now include.
  2. Check

    The connection dropped just after a mutation was sent. The client doesn't know if it committed, and resends it. What prevents it applying twice?