A courier taps "Delivered" in a basement with no signal, and what gets recorded is an intent, not a fact.
We ran into this building role-specific apps for couriers, warehouse staff and store operations. Field work happens exactly where connectivity dies: freight elevators, loading docks, cold rooms. The app has to accept the tap anyway, and the truth gets reconciled later.
Two things make that safe.
First, every action carries a client-generated operation id and the device timestamp of the tap. The id makes replays harmless when the queue retries. The timestamp preserves what actually happened, because sync order is not event order.
Second, the server applies a state machine instead of last write wins. A "picked up" that arrives after a "delivered" is not the newest truth. It is a late message, so it gets rejected or parked for a human, and it does not get written over a final state.
The part most teams skip is the UI. If a queued action looks identical to a confirmed one, the courier assumes the job is closed, and support inherits the gap between what the app shows and what the system knows. Pending has to look pending.
Offline-first is probably closer to a second source of events with its own ordering rules than to a caching feature. It belongs in the domain model rather than the network layer.
If you run field or warehouse apps, you end up choosing between auto-resolving the actions that sync hours late and parking them for a human.