Designing Offline-First Systems for Low-Connectivity Field Operations
Most "offline support" I've seen in web apps is really just a loading spinner that waits politely for the network to come back. That's fine for a dashboard. It's not fine for a field agent in a low connectivity area trying to redeem an in kind distribution token for someone standing right in front of them. The app has to actually work with no connection at all, not just fail a bit more gracefully.
Start from the failure mode, not the happy path
The real design question isn't what happens when the network is slow. It's what a field agent is doing right now with zero bars, and what correct behavior looks like in that exact moment. For token redemption that means a few things have to be true. The redemption itself needs to be recordable locally and immediately, with no round trip to a server. The beneficiary needs to walk away with their goods no matter when that record actually reaches the backend. And two agents shouldn't be able to accidentally redeem the same token twice once they're both back online.
Everything else in the architecture just follows from those three constraints.
Local first writes, eventual settlement
Every redemption gets written to local storage on the device first, tagged with a client generated idempotency key, a timestamp, and the agent's device ID. The UI treats that local write as the source of truth right away. There's no pending state the agent has to sit and babysit. A background sync process pushes queued redemptions to the server once connectivity comes back, in order, using that idempotency key so a redemption that partially synced and got retried doesn't end up counted twice.
Conflict resolution has to be decided ahead of time, not in code review
The hard part here isn't really the sync mechanism. It's deciding what "correct" even means when two devices redeem the same token while both are offline. For token based redemption specifically, I treat the token supply as the source of contention rather than the redemption event itself. The server is the final word on whether a token was still valid at settlement time, and a losing redemption gets flagged for manual review instead of silently dropped. Silently dropping a "second" redemption after someone has already handed over goods is worse than flagging it. You can reconcile a flagged case. You can't undo a distributed item that's already gone.
A few small things that mattered more than expected
Show connectivity state honestly. Agents need to actually know when they're offline instead of the app pretending everything is fine. Queue depth turned out to be a genuinely useful debugging tool too. Surfacing "twelve redemptions waiting to sync" caught more real issues during rollout than any error log did. And test on the actual hardware. Low end Android devices in the field behave differently under memory pressure than a simulator ever will show you.
Offline first isn't a checkbox you tick. It's a set of decisions about who wins when two truths disagree, and those need to get made before you write the sync code, not after.