You keep a shopping note on your phone and on your tablet. You are on a train with no signal, so you edit the note on your phone. Meanwhile your partner edits the same note on the tablet at home. Later, both devices get internet back. Which version should win?
This is one of the quiet hard problems of mobile apps. A phone is not always online, so a good app works from a local copy of your data (stored on the phone itself) and talks to a server (a computer on the internet that holds the shared copy) when it can. Sending your local changes to the server and fetching other people's changes is called syncing. Syncing is easy when only one device edits. It gets interesting when two devices change the same thing while apart. That clash is called a conflict.
Below are two phones that share one note. Switch a phone to airplane mode, edit it, then bring it back online. Try both rules, and compare what survives. A good first experiment: put both phones in airplane mode, change the title on Phone A and the note on Phone B, then bring both back online.
With last write wins, the app treats the whole note as one unit and keeps whichever copy was edited most recently. It is the simplest rule and it is common, but it throws away everything in the losing copy, even edits that never touched the same words. In the experiment above, the title typed on Phone A disappeared the moment Phone B's later edit won.
With field-by-field merging, the app keeps a time stamp for each field. Phone A changed the title and Phone B changed the note, so both changes can survive. Conflicts only remain when two devices change the same field, and then the newer edit still wins. Try that too: edit the same field on both phones while offline.
Here is the whole idea in about twenty lines of JavaScript. Each copy of the note remembers when each field was last edited.
const phoneA = { title: { value: "Groceries", time: 1 }, note: { value: "milk", time: 1 } };
const phoneB = { title: { value: "Groceries", time: 1 }, note: { value: "milk", time: 1 } };
// Both phones go offline. Each edits a DIFFERENT field.
phoneA.title = { value: "Party food", time: 5 };
phoneB.note = { value: "milk, eggs", time: 7 };
// Strategy 1: last write wins for the whole note
function lastWriteWins(a, b) {
const newest = (c) => Math.max(c.title.time, c.note.time);
return newest(a) > newest(b) ? a : b;
}
// Strategy 2: decide field by field
function mergeByField(a, b) {
const pick = (x, y) => (x.time >= y.time ? x : y);
return { title: pick(a.title, b.title), note: pick(a.note, b.note) };
}
const show = (r) => `${r.title.value} / ${r.note.value}`;
console.log("whole note:", show(lastWriteWins(phoneA, phoneB)));
console.log("by field: ", show(mergeByField(phoneA, phoneB)));
Running it in Node prints:
whole note: Groceries / milk, eggs
by field: Party food / milk, eggs
Phone A's new title, Party food, is lost by the first rule and kept by the second.
First, what is the unit? If the unit is the whole note, any two edits collide. If the unit is a field, only edits to the same field collide. The smaller the unit, the fewer conflicts, and the more bookkeeping you carry around (one time stamp per field instead of one per note).
Second, who decides? Sometimes the program decides, as in both rules above. Sometimes it is better to keep both versions and ask the person, the way some file-sync tools save a second copy next to the first.
Third, what is cheap to lose? A "last opened" date can be overwritten freely. A paragraph someone spent an hour writing cannot.
Our simulation uses a neat counter. Real phones have clocks that people can set wrong, and two devices rarely agree to the millisecond. So many systems let the server assign order, or attach version numbers to records instead of trusting device time. Others go further and use data structures designed so that edits made in any order always combine to the same result. Researchers call these CRDTs (conflict-free replicated data types). They are how some collaborative editors let two people type in the same sentence while offline. Reading about them is a good next step once the field-by-field idea feels natural.
When you build something that works offline, decide early: what is the unit of change (the whole note, a field, a single word), and what should happen when two devices change the same unit? Last write wins is a fine choice for data where losing an edit is cheap, such as a "last opened" date. For data people care about, like writing, tell the user when something was overwritten, or keep both versions. There is no single right answer, only trade-offs that you choose on purpose.