Journal

Local-First Database Conflict Resolution UI (Mobile)

Most conflicts should never reach the user; the few that do need a calm, honest screen.

Local-First Database Conflict Resolution UI (Mobile): a glass iPhone UI wireframe icon on a holographic purple gradient

TL;DR

Local-first apps store data on-device and sync in the background, so the hard part is conflicts. Resolve most automatically at the data layer (last-write-wins or CRDTs); for ambiguous cases, design a clear comparison screen from a free VP0 design with keep-mine, keep-theirs, and keep-both. Never silently drop an edit.

In a local-first app, data lives on the device and syncs in the background, so the app works offline and feels instant. The hard part is conflicts: when the same item is edited on two devices while offline, something has to reconcile them, and occasionally the user has to decide. The short answer is, resolve most conflicts automatically at the data layer and design a clear, rare conflict-resolution UI from a free VP0 design for the cases a human must settle. Most conflicts should never reach the user; the few that do need a calm, honest screen.

Why conflicts are the core problem

Local-first is great for users (instant, offline) but it shifts complexity to sync. The canonical reference, Ink and Switch’s local-first software essay, frames the goal as software that is both offline-capable and collaborative, which means merging concurrent edits. Most of that should be automatic, using strategies like last-write-wins or CRDTs at the data layer, so users never see a conflict. But some conflicts are genuinely ambiguous (two different edits to the same field) and need a human choice. Security matters here too, because synced data crosses the network and devices, and roughly 71% of mobile apps were found to leak sensitive data.

How to design the resolution UI

VP0 is a free iOS design library for AI builders. First, minimize what reaches the UI: choose a merge strategy at the data layer so most conflicts auto-resolve. For the rest, build a clear comparison screen from a VP0 design via Cursor or Claude Code: show both versions side by side (what is on this device vs the synced version), label which is which and when each changed, and offer “keep mine,” “keep theirs,” or “keep both.” Never silently drop a user’s edit. On iOS this often pairs with SwiftData or CloudKit for the store and sync; your UI is only the human-decision layer. For the data screen itself, see SwiftData UI template.

Conflict handling, by layer

Here is who should resolve what.

Conflict typeResolve where
Different fields editedAuto-merge (data layer)
Same field, clear recencyLast-write-wins (data layer)
Same field, ambiguousAsk the user (UI)
Deleted vs editedAsk the user (UI)
Anything sensitiveAuto + careful handling

A worked example

Say a notes app syncs across two devices. The user edits a note’s title on their phone and its body on their iPad while offline. Those are different fields, so the data layer merges them automatically and nothing reaches the UI. But if both devices edited the same title differently, show a VP0-designed conflict screen: “This note was changed on two devices,” the two titles with timestamps, and clear “keep this one,” “keep that one,” or “keep both as copies.” Make the choice obvious and reversible. For connecting the sync backend, see how to connect an API to an AI-built iOS app; for the live-preview workflow while building this, 21st.dev-style live preview for mobile app templates.

Common mistakes

The most common mistake is silently picking a winner and discarding the user’s edit, which destroys trust. The second is showing a conflict screen for things that could auto-merge, annoying users with decisions they should not have to make. The third is a confusing comparison that does not clearly label which version is which. The fourth is no “keep both” escape hatch for ambiguous cases. The fifth is ignoring the security of synced data, exactly the risk behind the 71% figure.

Key takeaways

  • Local-first feels instant and works offline, but conflicts are the core challenge.
  • Auto-resolve most conflicts at the data layer (last-write-wins or CRDTs) so users rarely see one.
  • For ambiguous conflicts, show a clear comparison UI with keep-mine, keep-theirs, and keep-both.
  • Never silently drop an edit, and handle synced data carefully since around 71% of apps leak data.

Frequently asked questions

How do I design conflict-resolution UI for a local-first app? Resolve most conflicts automatically at the data layer, and for the ambiguous ones build a clear comparison screen from a free VP0 design that shows both versions with timestamps and offers keep-mine, keep-theirs, or keep-both.

Should the user see every sync conflict? No. Most conflicts (edits to different fields, or a clear most-recent edit) should auto-merge at the data layer. Only genuinely ambiguous conflicts should reach the user.

What merge strategy should I use? Last-write-wins is simplest for clear recency; CRDTs handle concurrent edits more gracefully. Use the data layer (SwiftData, CloudKit, or a sync engine) for this and keep the UI for human decisions only.

What is the worst conflict-handling mistake? Silently discarding a user’s edit. Always preserve both versions when in doubt and let the user choose, with a reversible “keep both” option.

Frequently asked questions

How do I design conflict-resolution UI for a local-first app?

Resolve most conflicts automatically at the data layer, and for the ambiguous ones build a clear comparison screen from a free VP0 design that shows both versions with timestamps and offers keep-mine, keep-theirs, or keep-both.

Should the user see every sync conflict?

No. Most conflicts (edits to different fields, or a clear most-recent edit) should auto-merge at the data layer. Only genuinely ambiguous conflicts should reach the user.

What merge strategy should I use?

Last-write-wins is simplest for clear recency; CRDTs handle concurrent edits more gracefully. Use the data layer (SwiftData, CloudKit, or a sync engine) for this and keep the UI for human decisions only.

What is the worst conflict-handling mistake?

Silently discarding a user's edit. Always preserve both versions when in doubt and let the user choose, with a reversible keep-both option.

Part of the AI App Builders & Vibe Coding Tools hub. Browse all VP0 topics →

Keep reading

How to Build an iOS App With AI: A 2026 Guide: a phone toggle icon surrounded by location, calendar, settings, wallet and chart app icons on a coral gradient
Guides 5 min read

How to Build an iOS App With AI: A 2026 Guide

Start from a real iOS design, drive an AI builder like Claude Code, and ship to the App Store in days. The full workflow, tool by tool.

Lawrence Arya · May 28, 2026
Framer for iOS Apps: Where It Fits and Where It Stops: a glass photo icon surrounded by chat, music, heart, camera and shopping app icons on a pastel gradient
Guides 4 min read

Framer for iOS Apps: Where It Fits and Where It Stops

Framer is brilliant for design and prototypes, but it is web-first. See where Framer fits in an iOS workflow, and how to get from a Framer concept to a real app.

Lawrence Arya · May 31, 2026
React Native WebView Wrapper: Do It Without Getting Rejected: a glass photo icon surrounded by chat, music, heart, camera and shopping app icons on a pastel gradient
Guides 4 min read

React Native WebView Wrapper: Do It Without Getting Rejected

Wrapping a web app in React Native is tempting but risky. Build a WebView shell from a free VP0 design with native chrome and real native value.

Lawrence Arya · May 31, 2026
Capacitor Custom Native Header UI on iOS (Free Guide): the App Store logo as a glossy glass icon on a purple and blue gradient with floating bubbles
Guides 4 min read

Capacitor Custom Native Header UI on iOS (Free Guide)

A Capacitor app's web origin shows in the header. Make it native: respect the safe area, use iOS nav-bar conventions, and reference a free VP0 iOS design.

Lawrence Arya · May 30, 2026
Compose Multiplatform: iOS Look and Feel (Done Right): a glossy App Store icon on a blue, pink and orange gradient with bubbles
Guides 4 min read

Compose Multiplatform: iOS Look and Feel (Done Right)

Compose Multiplatform shares Kotlin UI but renders its own, so iOS feel is opt-in. Target Apple's HIG, not Material defaults; reference a free VP0 design.

Lawrence Arya · May 30, 2026
Flutter iOS Cupertino Widgets: Native-Feeling UI: a glossy App Store icon on a blue, pink and orange gradient with bubbles
Guides 4 min read

Flutter iOS Cupertino Widgets: Native-Feeling UI

Flutter's Cupertino widgets get an app close to iOS-native, but coverage is uneven. Target Apple's HIG, fill the gaps, and use a free VP0 design as your reference.

Lawrence Arya · May 30, 2026