By Allan Adan · May 2, 2026 · 3 min read

Local-First Sync: Strategies for Conflict Resolution

#mobile#engineering#Flutter

Local-first software grants each device a complete, writable copy of the data, allowing users to continue working without a network connection. This architecture delivers responsiveness and resilience, but it introduces an unavoidable consequence: two devices may independently modify the same record before they reconnect. The central engineering question is therefore not whether conflicts will occur, but how the system will reconcile them deterministically and without data loss. This article surveys the principal strategies for conflict resolution and the trade-offs that govern their selection.

The Source of Conflicts

A conflict arises whenever concurrent edits are applied to overlapping state on separate replicas. Because local-first systems deliberately permit writes during disconnection, divergence is the normal case rather than an exceptional one. The Ink & Switch articulation of local-first software frames this as a property to be embraced: software should keep working offline and synchronize seamlessly when connectivity returns. Achieving that goal requires a merge function that produces the same result regardless of the order in which devices exchange their changes.

Last-Write-Wins

The simplest strategy is last-write-wins, in which each value carries a timestamp and the most recent write supersedes the others. Its appeal is implementation cost: a single comparison resolves any disagreement. The weakness is silent data loss. If two users edit different fields of the same record, the losing record is discarded in its entirety even when the edits were not genuinely in conflict. Last-write-wins is acceptable for ephemeral or low-stakes data, such as a “last opened” marker, but it is poorly suited to user-authored content where every keystroke carries intent.

Operational Transformation

Operational transformation, the technique historically associated with collaborative text editors, represents edits as operations and transforms each incoming operation against operations that occurred concurrently. The result preserves user intent at fine granularity. The cost is substantial complexity: transformation functions must be defined for every pair of operation types and proven correct, and most production deployments depend on a central server to order operations. For an offline-first mobile application without a guaranteed coordinating server, this dependency is a meaningful constraint.

Conflict-Free Replicated Data Types

Conflict-free replicated data types, or CRDTs, offer a principled alternative. As described on CRDT.tech, a CRDT is a data structure whose merge operation is commutative, associative, and idempotent, which guarantees that all replicas converge to the same state once they have observed the same set of updates, irrespective of delivery order or duplication. CRDTs come in families: counters, registers, sets, sequences for ordered text, and maps that compose the simpler types. The practical advantage is that the developer reasons about data structures rather than about ad hoc merge code, and the convergence guarantee holds without a central authority. The trade-off is metadata overhead, since replicas must retain enough causal information to merge correctly, and certain semantics, such as removing an element that another replica concurrently updated, require deliberate design choices.

Selecting a Strategy

In my experience building offline-first Flutter applications, the appropriate strategy follows from the data, not from a single universal preference. Independent records keyed by stable identifiers tolerate last-write-wins at the record level with little risk. Collaboratively edited text benefits from a sequence CRDT. Structured documents are well served by a map CRDT composing field-level registers. A pragmatic system frequently combines approaches, applying coarse resolution where conflicts are rare and a convergent data type only where concurrent editing is genuinely expected.

Conclusion

Conflict resolution is the defining challenge of local-first synchronization, and no single strategy is correct for all data. Last-write-wins minimizes effort at the cost of potential loss; operational transformation preserves intent but typically presumes a coordinating server; CRDTs provide mathematically guaranteed convergence without central coordination, at the cost of additional metadata. The disciplined approach is to classify each category of data by its concurrency profile and apply the least complex strategy that preserves user intent, reserving convergent data types for the cases that demand them.

Working on something like this? Let's talk →

Sources & references (2)