← All postsEngineering

How to stop offline sync from silently overwriting someone else's edit

iotoms team · September 11, 2026 · 6 min read

A produce distributor running twelve routes out of two depots had a rep who'd spent fifteen minutes at a bakery customer's counter, working out a raised credit limit with the owner after a slow season. She updated the customer's profile in the field app right there — new limit, new terms — while it was fresh, still offline, phone tucked in a delivery bag two dead zones from a tower. Meanwhile, back at the office that same morning, someone in accounts had pulled up the same customer to correct a misspelled contact name on file. Small, unrelated change. They saved it around 10:40 a.m. The rep's phone found signal at 11:15 and synced.

By noon, the bakery's credit limit was back to its old number. Nobody had reversed it. Nobody had even opened that field. The office's 10:40 save had simply landed after the rep's 9:50 save reached the server, and the sync logic did the only thing it knew how to do: keep the most recent write and discard the other one, in full.

Why this looks like a smaller problem than it is

The instinct is to call this a rare coincidence — two people happening to touch the same record within an hour of each other. In a business with a handful of customers, maybe it is rare. Across a distributor with a few thousand active accounts, a dozen reps in the field, and an office staff editing records all day, the overlap window isn't the exception, it's a standing condition. Nobody involved gets a warning that it happened. The rep believes she raised the limit. The bakery believes it too, because she told them. The system believes something else, and the first anyone finds out is when the next order gets rejected at the old limit — in front of the customer, days later, when nobody remembers the conversation that set it.

The failure mode compounds because it's invisible until it isn't. Pricing overrides get similarly reverted. A route reassignment made in the office gets undone by a stale value still sitting on a rep's phone from before lunch. Each incident looks like an isolated glitch, gets manually fixed, and never gets traced back to the same root cause, because nothing in the system logged that a conflict happened at all — it just picked a winner and moved on.

Why "last write wins" is the default almost everyone starts with

Comparing timestamps and keeping the newer one is the simplest rule that can possibly work, and for a lot of offline sync it's fine — if two edits genuinely can't both be right, something has to give, and recency is a defensible tiebreaker. The trouble is that "last write wins" makes that call at the level of the whole record, not the field that actually conflicted. The rep's edit touched the credit limit. The office's edit touched a contact name. Nothing about those two changes was actually in conflict — they were changes to different facts about the same customer, made by two people who each had every right to make theirs. Treating the record as one atomic blob means the losing edit disappears completely, including the parts nobody was fighting over.

The other quiet assumption baked into last-write-wins is that "later" is knowable and means something. A phone that's been offline for six hours doesn't know what happened at the office in the meantime, and its own clock is only trustworthy if nobody's left a device on a stale battery or in a different time zone. Picking a winner by clock time treats a coincidence of timing as a decision about whose change matters more.

How to design around it instead

The fix has two parts, and the first one is cheap: stop merging at the record level and start merging at the field level. If the rep's sync only touched credit_limit and the office's sync only touched contact_name, both changes should land, because they never actually collided. This alone resolves the overwhelming majority of what looks like a conflict — most simultaneous edits to the same customer aren't really about the same fact.

That leaves a smaller, genuine case: two edits to the exact same field, from two sources, before either had seen the other's change. That's the one situation where a system has no honest way to guess which value should win — and the right move is not to guess. Surface it. Flag the record for a human to resolve, show both values and who made each one and when, and let the resolution be a deliberate choice rather than a side effect of network timing. This is rare enough, once field-level merging handles the rest, that it doesn't create real friction — but it means the one case that actually needs a decision gets one, instead of silently picking whichever write happened to arrive at the server last.

Underneath both of those, the sync needs to know what "unseen" means at all, which requires each record to carry a version marker that every edit references — so the system can tell "I'm updating the version I last saw" apart from "I'm updating a version two edits behind," instead of relying on wall-clock time.

What to check if you're evaluating a field sales system

  • Ask directly: if a rep and the office both edit the same customer while the rep is offline, what happens when the rep's device reconnects — does one edit disappear?
  • Ask whether sync merges at the level of individual fields or the whole record. Whole-record merging means unrelated changes can wipe each other out.
  • Ask what happens in the one case that's genuinely ambiguous — two edits to the same field. Is it flagged for someone to resolve, or silently decided by timestamp?
  • Test it: edit a customer's terms on a phone, put it in airplane mode, edit an unrelated field on the same account from the office, then reconnect the phone and confirm both changes survive.
  • Confirm the system can tell you when a conflict happened, even after the fact — a log a manager can check beats a change nobody knew to look for.

iotoms tracks customer and pricing records at the field level and versions every edit, so a rep's change in the field and an office update made the same morning merge instead of one silently erasing the other — and the rare case where two people genuinely change the same fact gets flagged for a person to settle, not decided by whichever save happened to land last.

See your own routes running on iotoms

Book a demo