Building the 72-Hour Offline POS: Sync Architecture and Conflict Resolution
When the internet goes down at a busy Pongal sale day — and in Indian retail, it will go down — the POS cannot stop. Customers do not stop wanting to buy just because the connection dropped. We built for that reality, not the ideal one.
When the internet goes down at a busy Pongal sale day — and in Indian retail, it will go down, because it always goes down when you need it most — the POS cannot stop. The queue of customers does not pause. The cashier does not have a 'wait for connectivity' button to press. Real commerce happens in the physical world, and the physical world has intermittent connectivity, especially in basements, rural areas, and large venues where the router has never been reliable.
We built our POS for that reality, not the ideal one. 72 hours of fully offline operation, with sync and conflict resolution when connectivity returns.
The On-Device Data Model
The 72-hour offline POS works because all the data it needs to function is on the device before connectivity is lost. The sync process runs continuously when connected, and the on-device SQLite database is always a recent replica of the server-side state for the relevant tenant and store location.
What lives on-device:
- The full product catalog with prices and GST rates (typically tens of thousands of SKUs)
- Active promotions and discount rules
- Customer loyalty balances for regulars (a rolling cache of the last 30 days of activity)
- Pending orders that have not yet been confirmed by the server
- The transaction queue — every sale completed offline, waiting for sync
What does not live on-device: real-time inventory counts for other store locations, new products added after the last sync, and payment gateway confirmations. These are acknowledged as 'pending server confirmation' and reconciled when connectivity returns.
The Sync Architecture
Sync runs as a background service inside the POS Capacitor app. When connected, it maintains a WebSocket connection to the sync server. Changes from the server (price updates, new promotions, catalog additions) arrive as a stream of events and are applied to the local SQLite database. Changes from the device (completed transactions, loyalty point accruals) are queued and sent to the server as they occur.
When connectivity is lost, the WebSocket closes and the local transaction queue begins accumulating. When connectivity returns, the queue replays to the server, and the server streams any missed server-side events to the device. The device is back in sync within seconds of reconnection, regardless of how long it was offline.
Conflict Resolution Rules
The hard part of offline sync is not syncing — it is resolving conflicts when two devices have made incompatible changes to the same data during a disconnected period.
We classify conflicts by data category, because the right resolution strategy varies:
- Inventory counts: Last-write-wins is wrong here (two devices selling the last unit of a product both report one sale, and the true inventory is zero, not negative one). We use a decrement model — each device records 'I sold N units' and the server applies all decrements to the last known stock level, allowing it to go negative (a flag for the merchant to reconcile).
- Loyalty point accruals: All accruals are additive and idempotent — we store the transaction ID with each accrual, so replaying the same accrual twice does not double-credit the customer.
- Promotions: Server-side promotions are authoritative. If a device applied a promotion that the server has since expired, the order is flagged for review but not automatically reversed — a human decision is required for customer-facing impacts.
The Reconciliation Step
When a device reconnects after an extended offline period, the server runs a reconciliation step: it replays all queued transactions in timestamp order, applies them to the authoritative state, and generates a reconciliation report for the merchant. The report shows any discrepancies — items sold that were already at zero inventory, promotions applied that had expired — and prompts the merchant to decide how to handle each one.
Most reconciliation reports are empty. The edge cases are rare in practice. But they are real, and ignoring them in the architecture would mean invisible data corruption that compounds over time.
Why 72 Hours?
We chose 72 hours as the design target because it covers the longest realistic offline period a retail location might face — a major connectivity outage, a natural disaster affecting infrastructure, or a sale event in a temporary venue with no fixed connectivity. Beyond 72 hours, we believe the merchant needs to assess the situation rather than continue operating blind.
The constraint is also practical: a 72-hour offline window requires a full product catalog on-device, which for large catalogs (50,000+ SKUs) requires non-trivial storage and sync planning. We made that investment because the alternative — a POS that stops working when the internet does — is not acceptable for the retail environments our tenants operate in.
Offline is not a degraded mode. It is a first-class mode.
Subscribe to the QuantumOS Dispatch — weekly insights for commerce operators who want to compound their advantages.
QuantumOS Dispatch
Weekly insights for commerce operators
100 competitive moats, real operator stories, platform updates. No fluff. Every Tuesday.
No spam. Unsubscribe any time. 60k+ readers.