Offline-first apps and data sync
A store's internet drops. Handscanners walk into the backstore where there is no signal. An offline-first app keeps working on its own copy of the data and syncs when the network is back, without losing or doubling anything. This lesson gives you the moving parts: local storage, a local outbox, push and pull with a cursor, tombstones, and conflict rules that fit the business.
By the end you can
- Decide which screens of an app need to work offline, and what "offline" promises the user
- Explain why devices create their own ids, and why sync uses a server sequence, not device clocks
- Build a pull endpoint with a
change_seqcursor and tombstones, and an idempotent push endpoint - Pick a conflict rule per field: last-write-wins, server-wins, merge, or append-only movements
- Sketch the React Native side: SQLite tables, a local outbox and a sync loop with backoff
The everyday picture
During a long internet outage, a careful store keeps a paper sales book at the counter. Each line gets a number written by hand: "Counter 2, slip 0147". When the line is back, someone types the slips into the system. If the power cuts in the middle, she looks at which slip numbers are already in the system and continues from there, so nothing is typed twice. And she does not write "stock of flour is now 38" in the book. She writes "sold 2 bags of flour", because head office may have received a delivery in the meantime, and only head office can add the two together correctly.
That paper book already contains every idea in this lesson: a local record, a unique number made at the counter, a way to know what was already sent, and recording what happened instead of what the total is.
Why offline-first, and what it promises
An offline-first app treats the network as a bonus. Every screen reads from a database on the device, every action writes there first, and a background process syncs with the server. The user never waits for the network to finish a task.
For stores this is not a luxury. Power cuts take down routers, mobile data is weak in backstores and cold rooms, and a festival rush can saturate the store's link. A handscanner that freezes during a stock count wastes an hour of staff time. A POS that cannot sell during an outage loses sales outright. In CAP terms (see CAP, PACELC and consistency), these features choose availability: keep working during the partition, and reconcile afterwards.
Not every feature should work offline. Ask, per action, "is it safe to accept this without the server?"
- Safe offline: scanning items in a stock count, recording a GRN that arrived, marking damaged stock, cash sales, reading the price list and product catalogue.
- Needs the server: reserving scarce stock for a partner shop order (see Events, the outbox pattern and sagas), approving a price override above a limit, wallet payments that must be confirmed. Offline, these should say clearly "needs a connection" or be queued as a request that can still be refused.
Quick check
The Store app is offline. Which action should it refuse, or queue as a request the server can still turn down?
An approval above a limit is a decision only the server (and the person who sets limits) can make, so accepting it offline would bypass the rule. Scans, damage records and price reads are facts or reads that stay safe when they reach the server later.