ऐसे ऑफलाइन-फर्स्ट मोबाइल ऐप सिंक नियम जो उपयोगकर्ता समझ सकें: स्पष्ट कन्फ्लिक्ट पैटर्न, सरल स्थिति संदेश, और ऐसी कॉपी जो ऑफलाइन भ्रम घटाए।

अधिकांश लोग नेटवर्क के बारे में नहीं सोचते। वे अपने सामने के काम के बारे में सोचते हैं। अगर वे अभी भी टाइप कर सकते हैं, Save दबा सकते हैं, या स्क्रीन पर बदलाव देख सकते हैं, तो वे मान लेते हैं कि यह काम हो गया।
उनकी अपेक्षाएँ आमतौर पर कुछ नियमों में सिमट जाती हैं:
इनके पीछे दो भय होते हैं: खोया हुआ काम और आश्चर्यजनक बदलाव।
खोया हुआ काम धोखे जैसा लगता है क्योंकि ऐप ने उन्हें जारी रखने दिया। आश्चर्यजनक बदलाव और भी बुरा लग सकता है क्योंकि बाद में ऐप ने ऐसा किया जैसे उसने “मन बदल लिया”।
इसीलिए आपको “synced” को साधारण शब्दों में परिभाषित करना होगा। Synced का मतलब यह नहीं है कि “मैं इसे अपने फोन पर देख पा रहा/रही हूँ।” इसका मतलब है “यह परिवर्तन सर्वर को अपलोड हुआ और सर्वर ने इसे स्वीकार कर लिया है, और दूसरे डिवाइसों पर भी दिखेगा।” आपकी UI लोगों को यह समझने में मदद करनी चाहिए कि वे किस स्थिति में हैं।
एक सामान्य विफलता का दृश्य: कोई व्यक्ति सबवे में अपना शिपिंग एड्रेस एडिट करता है, उसे अपडेट होते देखता है और ऐप बंद कर देता है। बाद में वह घर पर खोलता है और पुराना पता वापस आ जाता है। भले ही सिस्टम ने कुछ तार्किक किया हो, उपयोगकर्ता इसे डेटा लॉस के रूप में अनुभव करता है।
नियत नियम और स्पष्ट संदेश इस सब का अधिकांश भाग रोकते हैं। “Saved on this device” बनाम “Synced to your account” जैसी छोटी स्थिति पंक्तियाँ बहुत काम करती हैं।
एक अच्छा ऑफलाइन-फर्स्ट दृष्टिकोण एक सरल वादा से शुरू होता है: जब आप Save दबाते हैं, आपका काम अभी सुरक्षित है, भले ही इंटरनेट न हो।
जब उपयोगकर्ता कुछ एडिट करता है, ऐप को उसे पहले डिवाइस पर सेव कर देना चाहिए। यही वह वर्शन होना चाहिए जिसे वे तुरंत देखने की उम्मीद करें।
अलग से, ऐप कोशिश करता है उस परिवर्तन को सर्वर पर भेजने की जब संभव हो। अगर फोन ऑफलाइन है, तो वे एडिट्स “खोए” या “आधे सेव” नहीं हैं। वे बस भेजे जाने का इंतजार कर रहे होते हैं।
UI में तकनीकी शब्दों जैसे “queued” या “pending writes” से बचें। साधारण भाषा अपनाएँ: “हम आपके बदलाव भेज देंगे जब आप फिर से ऑनलाइन होंगे।”
लोग तब शांत महसूस करते हैं जब ऐप स्पष्ट रूप से दिखाता है कि वह किस स्थिति में है। आप अधिकांश परिस्थितियों को कुछ ही स्थितियों के सेट से कवर कर सकते हैं:
फिर एक विशेष स्थिति जोड़ें जब ऐप वास्तव में उपयोगकर्ता की हस्तक्षेप के बिना पूरा नहीं कर सकता: Needs attention.
एक सरल विज़ुअल सिस्टम अच्छा काम करता है: एक छोटा आइकन और उस क्रिया के पास एक छोटी टेक्स्ट लाइन (उदाहरण के लिए, एडिट स्क्रीन के नीचे)।
उदाहरण कॉपी:
एक सिंक कन्फ्लिक्ट तब होता है जब एक ही चीज़ पर दो एडिट्स हो जाते हैं इससे पहले कि ऐप सर्वर के साथ “नोट्स” की तुलना कर सके।
कन्फ्लिक्ट आमतौर पर सामान्य व्यवहार से आते हैं:
जो लोगों को चौंकाता है वह यह है कि उन्होंने कुछ गलत नहीं किया। उन्होंने अपना एडिट लोकली सफल होते देखा, इसलिए वे मान लेते हैं कि यह अंतिम है। जब ऐप बाद में सिंक करता है, तो सर्वर इसे अस्वीकार कर सकता है, किसी अनपेक्षित तरीके से जोड़ सकता है, या किसी और के वर्शन से बदल सकता है।
सभी डेटा का जोखिम समान नहीं होता। कुछ बदलावों को नाटक के बिना सुलझाया जा सकता है (लाइक्स, पढ़ा/नपढ़ा, कैश्ड फिल्टर्स)। दूसरे अधिक संवेदनशील होते हैं (शिपिंग एड्रेस, कीमतें, इन्वेंटरी काउंट, भुगतान)।
सबसे बड़ा भरोसा-टूटने वाला दृश्य है चुपचाप ओवरराइट होना: ऐप उपयोगकर्ता का ऑफलाइन बदलाव चुपके से सर्वर के नए वर्शन से बदल देता है (या इसके विपरीत) बिना किसी संदेश के। लोग बाद में नोटिस करते हैं, आमतौर पर जब बात महत्वपूर्ण होती है, और फिर सपोर्ट टिकट आते हैं।
आपके नियमों को एक बात को पूर्वानुमेय बनाना चाहिए: उनका बदलाव जीत जाएगा, मिलाया जाएगा, या उपयोगकर्ता से विकल्प मांगेगा?
जब ऐप ऑफलाइन बदलाव सेव करता है, तो अंततः उसे तय करना होता है कि अगर वही आइटम कहीं और भी बदला गया है तो क्या करना है। लक्ष्य पूर्णता नहीं है। लक्ष्य है व्यवहार जिसे उपयोगकर्ता भविष्यवाणी कर सकें।
Last-write-wins का मतलब है सबसे हालिया एडिट अंतिम वर्शन बन जाता है। यह तेज और सरल है, लेकिन यह किसी और के काम को ओवरराइट कर सकता है।
इसे तब उपयोग करें जब गलती सस्ती और आसान हो, जैसे पढ़ा/नपढ़ा स्टेट, सॉर्ट ऑर्डर, या “last viewed” टाइमस्टैम्प। अगर आप LWW इस्तेमाल करते हैं, तो समझौता छुपाएँ नहीं। स्पष्ट कॉपी मदद करती है: “Updated on this device. If a newer update exists, it may replace this one.”
Merge का मतलब है ऐप दोनों सेट्स को जोड़ने की कोशिश करता है। यह उन मामलों में अच्छा है जहाँ लोग उम्मीद करते हैं कि एडिट्स जमा होंगे, जैसे किसी लिस्ट में आइटम जोड़ना, संदेश जोड़ना, या प्रोफ़ाइल के अलग-अलग फ़ील्ड्स को एडिट करना।
सफल होने पर संदेश शांत और विशिष्ट रखें:
अगर कुछ मिलाया नहीं जा सका, तो साफ़ बताइए कि क्या हुआ:
पूछना वह विकल्प है जब डेटा महत्वपूर्ण हो और स्वचालित निर्णय से वास्तविक नुकसान हो सकता है, जैसे भुगतान, अनुमतियाँ, मेडिकल जानकारी, या कानूनी टेक्स्ट।
व्यवहारिक नियम का अंगूठा:
Last-write-wins (LWW) सुनने में सीधा लगता है: जब एक ही फ़ील्ड दो जगहों पर एडिट हो, तो सबसे नया एडिट सहेजा जाएगा। भ्रम यह आता है कि “नया” का असल मतलब क्या है।
आपको एक एकल समय स्रोत चाहिए वरना LWW जल्दी गड़बड़ हो जाता है।
सबसे सुरक्षित विकल्प सर्वर समय है: सर्वर हर बदलाव को प्राप्त करने पर एक “updated at” असाइन करता है, फिर नवीनतम सर्वर टाइमस्टैम्प जीतता है। अगर आप डिवाइस समय पर निर्भर करते हैं, तो गलत क्लॉक वाला फोन सही डेटा को ओवरराइट कर सकता है।
सर्वर समय के साथ भी, LWW लोगों को चौंका सकता है क्योंकि “सर्वर तक पहुंचने वाला आखिरी बदलाव” उनके किए गए “आखिरी” बदलाव जैसा महसूस नहीं होता। एक धीमा कनेक्शन आगमन के क्रम को बदल सकता है।
LWW उन मानों के लिए सबसे अच्छा काम करता है जहाँ ओवरराइट होना स्वीकार्य हो, या जहाँ सिर्फ नवीनतम मान मायने रखता हो: प्रेज़ेंस फ्लैग्स (ऑनलाइन/अफलाइन), सेशन सेटिंग्स (म्यूट, सॉर्ट ऑर्डर) और इसी तरह के कम-जोखिम फ़ील्ड्स।
जहाँ LWW नुकसान पहुँचाता है वह है मायने रखने वाला, ध्यान से एडिट किया गया कंटेंट: प्रोफ़ाइल जानकारी, पते, मूल्य, लंबा टेक्स्ट, या जो कुछ भी उपयोगकर्ता “गायब” होना पसंद नहीं करेंगे। एक साइलेंट ओवरराइट डेटा लॉस जैसा महसूस करवा सकता है।
समझ को कम करने के लिए, परिणाम को दृश्यमान और दोष-मुक्त बनाएं:
Merge तब सबसे अच्छा काम करता है जब लोग बिना मदद के नतीजे का अनुमान लगा सकें। सबसे सरल तरीका है: सुरक्षित चीज़ों को मिलाएँ, केवल तब रोकें जब आप नहीं कर सकते।
किसी पूरे प्रोफ़ाइल का एक वर्शन चुनने की बजाय फ़ील्ड के हिसाब से मिलाएँ। अगर एक डिवाइस ने फोन नंबर बदला और दूसरे ने पता बदला, तो दोनों रखें। यह निष्पक्ष लगता है क्योंकि उपयोगकर्ता अप्रसंगिक एडिट्स नहीं खोते।
सफल होने पर सहायक कॉपी:
अगर किसी फ़ील्ड में कन्फ्लिक्ट हो, तो स्पष्ट कहें:
कुछ डेटा प्रकार स्वाभाविक रूप से जोड़ने योग्य होते हैं: कमेंट्स, चैट संदेश, एक्टिविटी लॉग, रसीदें। अगर दो डिवाइस ऑफलाइन होने पर आइटम जोड़ते हैं, तो आम तौर पर आप सभी को रख सकते हैं। यह सबसे कम भ्रम वाला पैटर्न है क्योंकि कुछ ओवरराइट नहीं होता।
साफ स्थिति संदेश:
सूचियाँ तब पेचीदा हो जाती हैं जब एक डिवाइस किसी आइटम को हटाता है और दूसरे ने उसी आइटम को एडिट किया। एक सरल नियम चुनें और इसे नंगे शब्दों में बताइए।
एक सामान्य दृष्टिकोण: एड्स हमेशा सिंक होते हैं, एडिट्स तब तक सिंक होते हैं जब तक आइटम हटाया न गया हो, और डिलीट एडिट पर जीत जाता है (क्योंकि आइटम गायब है)।
कन्फ्लिक्ट कॉपी जो घबराहट रोकती है:
जब आप इन चुनावों को साधारण भाषा में दस्तावेज़ करते हैं, तो लोग अनुमान लगाना बंद कर देते हैं। सपोर्ट टिकट घटते हैं क्योंकि ऐप का व्यवहार स्क्रीन पर दिखाए गए संदेश से मेल खाता है।
अधिकांश कन्फ्लिक्ट्स के लिए डायलॉग की ज़रूरत नहीं होती। केवल तभी पूछें जब ऐप सुरक्षित विजेता चुनने में असमर्थ हो और इससे आश्चर्य हो सकता हो, जैसे दो लोगों ने एक ही फ़ील्ड को अलग-अलग तरीकों से बदला हो।
सिंक पूरा होने के ठीक बाद एक साफ पल पर बाधित करें: जब कन्फ्लिक्ट पता चले। अगर डायलॉग तब पॉपअप हो जब उपयोगकर्ता टाइप कर रहा हो, तो यह ऐसा लगेगा जैसे ऐप उनका काम तोड़ रहा है।
संभव हो तो विकल्पों को दो बटनों तक ही रखें। “Keep mine” बनाम “Use theirs” आम तौर पर काफी होता है।
साधारण भाषा का उपयोग करें जो उपयोगकर्ता को याद हो कि उन्होंने क्या किया था:
तकनीकी डिफ़ की बजाय, फर्क को एक छोटी कहानी की तरह बताइए: “You changed the phone number to 555-0142. Someone else changed it to 555-0199.”
डायलॉग टाइटल:
We found two versions
डायलॉग बॉडी उदाहरण:
Your profile was edited on this phone while offline, and it was also updated on another device.
This phone: Phone number set to (555) 0142 Other update: Phone number set to (555) 0199
बटन:
Keep mine
Use theirs
चुनने के बाद पुष्टिकरण:
Saved. We’ll sync your choice now.
अगर आपको थोड़ा अतिरिक्त आश्वासन चाहिए तो बटनों के नीचे एक शांत लाइन जोड़ें:
You can change this again later in Profile.
शुरू करें यह तय कर के कि लोग बिना कनेक्शन के क्या कर सकते हैं। अगर आप उपयोगकर्ताओं को सब कुछ ऑफलाइन एडिट करने देते हैं, तो आप बाद में अधिक कन्फ्लिक्ट स्वीकार करते हैं।
एक सरल आरंभिक बिंदु: ड्राफ्ट और नोट्स संपादन योग्य रखें; अकाउंट सेटिंग्स सीमाओं के साथ एडिट करने योग्य रखें; संवेदनशील कार्रवाईयाँ (भुगतान, पासवर्ड बदलना) ऑनलाइन होने तक केवल देखें।
अगला, प्रत्येक डेटा प्रकार के लिए एक कन्फ्लिक्ट नियम चुनें, पूरे ऐप के लिए एक नियम नहीं। नोट्स अक्सर मर्ज हो सकते हैं। प्रोफ़ाइल फ़ील्ड सामान्यतः नहीं। भुगतान बिल्कुल भी कन्फ्लिक्ट नहीं होना चाहिए। यहीं आप नियमों को साधारण भाषा में परिभाषित करते हैं।
फिर उन दृश्यमान स्थितियों का नक्शा बनाइए जो उपयोगकर्ता देखेंगे। स्क्रीनों के पार उन्हें सुसंगत रखें ताकि लोगों को बार-बार सीखने की जरूरत न पड़े। उपयोगकर्ता-उन्मुख टेक्स्ट के लिए, “Saved on this device” और “Waiting to sync” जैसे वाक्य पसंद करें जो आंतरिक शर्तों पर भारी न हों।
कॉपी लिखें जैसे आप इसे एक दोस्त को समझा रहे हों। अगर आप “conflict” शब्द का उपयोग करते हैं, तो तुरंत बताइए: “दो अलग एडिट्स हुए जब आपके फोन ने सिंक नहीं किया था।”
शब्दों को गैर-टेक उपयोगकर्ताओं के साथ टेस्ट करें। हर स्क्रीन के बाद एक प्रश्न पूछें: “आपको लगता है अब क्या होगा?” अगर उनका अनुमान गलत है, तो कॉपी अपना काम नहीं कर रही।
अंत में, एक एस्केप हैच जोड़ें ताकि गलतियाँ स्थायी न हों: हालिया एडिट्स के लिए undo, महत्वपूर्ण रिकॉर्ड्स के लिए वर्शन हिस्ट्री, या रिस्टोर पॉइंट्स। Koder.ai जैसी प्लेटफ़ॉर्म स्नैपशॉट और रोलबैक का उपयोग करते हैं—इसी कारण जब किन्हीं एज-केसेस होते हैं, तो रिकवरी भरोसा बनाती है।
अधिकांश सिंक सपोर्ट टिकट एक मूल समस्या से आते हैं: ऐप जानता है क्या चल रहा है, पर उपयोगकर्ता नहीं जानता। स्थिति को दृश्यमान बनाइए और अगला कदम स्पष्ट रखिए।
“Sync failed” एक डेड एंड है। बताइए क्या हुआ और उपयोगकर्ता क्या कर सकता है।
बेहतर: “Couldn’t sync right now. Your changes are saved on this device. We’ll try again when you’re online.” अगर कोई विकल्प है, तो उसे दें: “Try again” और “Review changes waiting to sync.”
अगर लोग अपने भेजे न गए अपडेट नहीं देख पाते, तो वे समझते हैं कि काम चला गया। उन्हें एक जगह दीजिए जहाँ वे पुष्टि कर सकें कि क्या लोकली स्टोर है।
एक सरल तरीका है एक छोटी स्थिति लाइन जैसे “3 changes waiting to sync” जो एक छोटा लिस्ट खोलती है आइटम नामों और मोटे समयों के साथ।
लो-स्टेक फ़ील्ड्स के लिए ऑटो-रिज़ॉल्व ठीक हो सकता है, लेकिन जब यह कुछ मायने रखता है (पते, कीमतें, अनुमोदन) और बिना निशान के ओवरराइट कर देता है तो गुस्सा आता है।
कम से कम, एक्टिविटी हिस्ट्री में एक नोट छोड़े: “We kept the most recent version from this device” या “We combined changes.” बेहतर: पुन: कनेक्शन के बाद एक एक-बार का बैनर दिखाएँ: “We updated 1 item during sync. Review.”
उपयोगकर्ता समय से निष्पक्षता आकलन करते हैं। अगर आपका “Last updated” सर्वर समय या अलग टाइमज़ोन इस्तेमाल करता है, तो यह ऐसा लग सकता है कि ऐप ने उनके पीछे कुछ बदल दिया।
समय उपयोगकर्ता के लोकल टाइमज़ोन में दिखाएँ, और विचार करें मित्रवत वाक्य जैसे “Updated 5 minutes ago.”
ऑफलाइन सामान्य है। रोज़मर्रा के डिसकनेक्शनों के लिए डरावने लाल स्टेट्स से बचें। शांत भाषा का उपयोग करें: “Working offline” और “Saved on this device.”
अगर कोई ट्रेन में प्रोफ़ाइल एडिट करता है और बाद में वाई-फाई पर पुराना डेटा देखता है, तो वे शायद सपोर्ट को नहीं बताएँगे अगर ऐप स्पष्ट रूप से दिखाता है “Saved locally, will sync when online” और फिर “Synced” या “Needs attention.” अगर यह सिर्फ दिखाए “Sync failed,” तो वे रिपोर्ट करेंगे।
अगर लोग आपके सिंक व्यवहार का अनुमान नहीं लगा सकते, तो वे ऐप पर भरोसा छोड़ देते हैं।
ऑफ़लाइन स्थिति को नजरअंदाज करना मुश्किल बनाइए। हेडर में एक छोटा बैज अक्सर काफी होता है, पर यह तब दिखना चाहिए जब यह मायने रखता है (एयरप्लेन मोड, सिग्नल नहीं, या सर्वर पहुंचनीय नहीं) और वापस ऑनलाइन होते ही जल्दी गायब होना चाहिए।
फिर उपयोगकर्ता के Save दबाने के बाद के पल की जाँच करें। उन्हें तुरंत पुष्टि दिखनी चाहिए कि बदलाव लोकली सुरक्षित है, भले ही सिंक न हो सके। “Saved on this device” घबराहट और बार-बार टैप करने को कम कर देता है।
एक छोटी चेकलिस्ट आपकी फ्लो को सत्यापित करने के लिए:
रिकवरी को सामान्य महसूस कराइए। अगर last-write-wins ने कुछ ओवरराइट कर दिया, तो “Undo” या “Restore previous version” दें। अगर आप यह नहीं दे सकते, तो एक साधारण अगला कदम बताइए: “Try again when online,” और सपोर्ट से जुड़ने का स्पष्ट तरीका दें।
एक सरल परीक्षण: किसी मित्र से कहें कि वे ऑफलाइन जाएँ, एक फ़ील्ड एडिट करें, फिर दूसरे डिवाइस पर वही फ़ील्ड एडिट करें। अगर वे बिना अनुमान लगाए बता सकें कि क्या होगा, तो आपके नियम काम कर रहे हैं।
माया ट्रेन में है, सिग्नल नहीं है। वह अपनी प्रोफ़ाइल खोलती है और डिलीवरी पता बदलती है:
“12 Oak St, Apt 4B” से “12 Oak St, Apt 4C”।
स्क्रीन के ऊपर वह देखती है: “You’re offline. Changes will sync when you’re back online.” वह Save दबाती है और आगे बढ़ती रहती है।
इसी समय, उसका पार्टनर एलेक्स घर पर ऑनलाइन है और एक ही पते को अपने शेयर्ड खाते में बदल कर “14 Pine St” कर देता है। एलेक्स सेव करता है और यह तुरंत सिंक हो जाता है।
जब माया सिग्नल पाती है, वह देखती है: “Back online. Syncing your changes…” फिर एक टोस्ट: “Synced.” आगे क्या होता है यह आपके कन्फ्लिक्ट नियम पर निर्भर करता है।
Last-write-wins: माया का एडिट बाद में हुआ, इसलिए पता “12 Oak St, Apt 4C” बन जाता है। एलेक्स आश्चर्यचकित होगा क्योंकि उनका बदलाव “गायब” हो गया। बेहतर फॉलो-अप संदेश: “Synced. Your version replaced a newer update from another device.”
Field-level merge: अगर एलेक्स ने स्ट्रीट बदला और माया ने सिर्फ अपार्टमेंट नंबर बदला, तो आप उन्हें मिला सकते हैं: “14 Pine St, Apt 4C”. टोस्ट कह सकता है: “Synced. We combined changes from another device.”
Ask the user: अगर दोनों ने एक ही फ़ील्ड (स्ट्रीट लाइन) बदला, तो एक शांत प्रॉम्प्ट दिखाएँ:
“Two updates to Delivery address”
“We found changes from another device. Nothing was lost. Choose which one to keep.”
बटन: “Keep mine” और “Use other update”।
उपयोगकर्ता जो सीखता है वह सरल है: सिंक पूर्वानुमेय है, और अगर टकराव हुआ तो कुछ भी खोया नहीं—वे चुन सकते हैं।
अगर आप चाहते हैं कि उपयोगकर्ता पूर्वानुमेय ऑफलाइन व्यवहार पाएं, तो पहले अपने नियम साधारण वाक्यों में लिखें। एक सहायक डिफ़ॉल्ट: कम-जोखिम फ़ील्ड (नोट्स, टैग, विवरण) के लिए merge, पर उच्च-जोखिम डेटा (भुगतान, इन्वेंटरी काउंट, कानूनी टेक्स्ट) के लिए Ask चुनें।
इन नियमों को एक छोटे कॉपी किट में बदलें जिसे आप हर जगह पुन: उपयोग कर सकें। शब्दावली सुसंगत रखें ताकि उपयोगकर्ता एक बार सीख लें और फिर बार-बार न सीखना पड़े।
पूर्ण फीचर बनाने से पहले स्क्रीन और कॉपी का प्रोटोटाइप बनाइए। आप पूरी कहानी देखना चाहेंगे: ऑफलाइन रहते हुए एडिट, फिर री-कनेक्ट, सिंक, और जब टकराव हो तो क्या होता है।
एक हल्का-फुल्का टेस्ट प्लान जो अधिकांश भ्रम पकड़ लेता है:
अगर आप Koder.ai का उपयोग कर रहे हैं, तो planning mode आपकी मदद कर सकता है ऑफलाइन स्थितियों का नक्शा बनाने और सटीक संदेश तैयार करने में, फिर एक त्वरित Flutter प्रोटोटाइप जनरेट करने में ताकि आप पूरी बिल्ड पर जाने से पहले फ्लो को मान्य कर सकें।
Default to: save locally first, then sync later.
When the user taps Save, confirm immediately with copy like “Saved on this device.” Then, separately, sync to the server when a connection is available.
Because seeing an edit on screen only proves it’s stored on that device right now.
“Synced” should mean: the change was uploaded, accepted by the server, and will appear on other devices too.
Keep it small and consistent:
Pair one icon with one short status line near the action that mattered.
Use plain language and say what’s safe:
Avoid technical terms like “queued writes” or “pending mutations.”
A conflict happens when two different edits hit the same item before the app can sync and compare with the server.
Common causes:
Use last-write-wins only for low-stakes values where overwriting is cheap, like:
Avoid it for addresses, prices, long text, approvals, and anything users would feel as “lost work.”
Prefer server time.
If devices decide “latest” using their own clocks, a wrong device time can overwrite correct data. With server time, “last” becomes “last received and accepted by the server,” which is at least consistent.
Use merge when users expect both changes to survive:
If a specific field can’t be merged, say exactly what you kept and why in one sentence.
Ask only when being wrong is expensive (money, permissions, legal/medical info).
Keep the dialog simple:
Make waiting changes visible.
Practical options:
Also add recovery when possible (undo, version history, snapshots/rollback) so mistakes aren’t permanent—tools like Koder.ai use snapshots and rollback for this reason.