Part 3: Conflict Resolution in Offline-First Android Apps (LWW vs. CRDT Explained)

 A Senior Engineer’s guide to LWW, Semantic Merging, and CRDTs for bulletproof data integrity.

Conflict Resolution in Offline-First Android Apps (LWW vs. CRDT Explained)

TL;DR

  • Conflicts are unavoidable in offline-first apps; ignoring them leads to silent data loss.
  • LWW (Last Writer Wins) is the simplest strategy but the riskiest.
  • Semantic Merge is the industry standard for 90% of mobile apps.
  • CRDTs are the gold standard for real-time collaborative editing.
  • Integrity requires atomic transactions between your local DB and the Sync Outbox.

1. The Anatomy of a Conflict

When multiple devices update the same data without a persistent connection, conflict resolution in distributed systems becomes your top priority.

Visualizing the Collision

  • The Stale Read (Lost Update): Your app reads a profile at v1. While offline, a web dashboard updates it to v2. The app eventually syncs its edit based on v1, wiping out the server’s newer data.
  • The Write-Write Conflict: Device A sets a status to “Done,” while Device B sets it to “In Progress” simultaneously.

2. API-Level Detection: The If-Match Header

A robust mobile sync engine doesn’t just send a blind PUT request. It uses Optimistic Concurrency Control.

The Flow:

  1. Client sends: PUT /profile with header If-Match: version=42.
  2. If the server is already at version=43, it returns a 412 Precondition Failed.
  3. The app identifies this as a Conflict and triggers the resolution logic instead of overwriting data.

3. Best Conflict Resolution Strategies for Android Apps

Press enter or click to view image in full size
Best Conflict Resolution Strategies for Android Apps
Best Conflict Resolution Strategies for Android Apps

LWW: The Hammer

The server accepts the most recent timestamp. However, data consistency in mobile apps suffers here because mobile clocks are unreliable due to clock skew. Never trust the device time for absolute truth.

Semantic Merge: The Scalpel

This resolves conflicts by merging specific fields rather than whole objects.

// Example: Field-Level Merge
fun resolveConflict(local: UserProfile, remote: UserProfile): UserProfile {
return remote.copy(
bio = if (local.bio != remote.bio) local.bio else remote.bio,
theme = if (local.theme != remote.theme) local.theme else remote.theme
)
}

4. What Companies Actually Do

  • Instagram: Uses Optimistic UI + Eventual Consistency. The UI updates instantly, and the “Like” or “Comment” eventually propagates. If a conflict occurs (e.g., liking a deleted post), it silently rolls back.
  • Google Docs / Figma: Use CRDTs (Conflict-free Replicated Data Types) or OT (Operational Transformation) to ensure every keystroke from every user is mathematically merged.
  • Most Enterprise Apps: Use Semantic Merge + Versioning. They track changes at the field level and use version tokens to detect collisions.

5. The Golden Rule: Atomic Transactions

In any offline-first Android app, your local state and your sync intent must be a single unit of work.

// The "All-or-Nothing" Guard
db.withTransaction {
userDao.update(localProfile)
// If the outbox write fails, the local DB update is rolled back.
outboxDao.insert(PendingAction(type = "SYNC_PROFILE", payload = json))
}

6. Decision Guide: Rule of Thumb

  • If the data is replaceable: (e.g., a “Last Viewed” timestamp) → Use LWW.
  • If fields are independent: (e.g., a user updating their bio while another updates the avatar) → Use Semantic Merge.
  • If the data is collaborative: (e.g., shared documents or whiteboards) → Use CRDTs.

Architect’s Challenge: Let’s Discuss

  • The Burn: Did a Last Writer Wins policy ever cause silent data loss for your users?
  • The Choice: Have you ever attempted to implement CRDTs, or did you stick to Semantic Merging?

Curious to hear your real-world war stories in the comments below! 👇

Series Navigation

In Part 4, we move from architecture to “Day 2” problems: Observability, Security, and Traffic Spikes.

📘 Master Your Next Technical Interview

Since Java is the foundation of Android development, mastering DSA is essential. I highly recommend “Mastering Data Structures & Algorithms in Java”. It’s a focused roadmap covering 100+ coding challenges to help you ace your technical rounds.


Comments

Popular posts from this blog

No More _state + state: Simplifying ViewModels with Kotlin 2.3

Why You Should Stop Passing ViewModels Around Your Compose UI Tree 🚫

Is Jetpack Compose Making Your APK Fatter? (And How to Fix It)