Local-First
CRDT
Sincronização de Dados
Arquitetura
Tempo Real

CRDTs: How to Sync Serverless Data to Arbitrate Conflicts

CRDTs solve the hardest local-first problem: merging offline edits without losing data and without a central server to decide who wins.

CRDTs: How to Sync Serverless Data to Arbitrate Conflicts

Imagine two users editing the same document on different planes, without internet. Each changes the same field. When they land and the devices sync, someone needs to decide which version wins. The traditional answer was simple and brutal: the last one to save overwrites the previous one. The other loses his job and doesn't even realize it.

This is the core problem of any local-first application. Data lives on the device first, editing happens offline, and reconciliation comes later. The question is not whether there will be conflict, it is how to merge two divergent truths without losing information and, ideally, without relying on a central server acting as a judge. CRDTs are the most elegant mathematical answer we have for this.

What is a CRDT, without mysticism

CRDT stands for Conflict-free Replicated Data Type. The name scares more than the concept. In practice, it is a data structure designed so that multiple copies can be edited independently and, when they meet, they automatically converge to the same final state, without prior coordination.

The keyword is convergence. It doesn't matter the order in which the changes arrive, nor how many times the same change is applied, nor how many hops it has passed through the network. If two devices see the same set of operations, they end up identical. This guarantee is mathematical, not a promise of code goodwill.

To achieve this, the operations of a CRDT must have three properties. They are commutative, so the order does not change the result. They are associative, so the grouping does not matter. And they are idempotent, so applying the same thing twice doesn't cause damage. Structures that respect these rules form what mathematics calls semilattice, and this is where the guarantee of convergence comes from.

Why this solves the local-first problem

Without CRDTs, syncing offline requires an arbiter. Normally a server that receives all versions, applies any rule, often the infamous last-write-wins, and returns the official truth. This has two costs. The data lost in overwriting, and the dependence on a central point always online to resolve any divergence.

CRDTs dissolve this dependency. Because merging is deterministic and built into the fabric itself, any device can merge with any other, in any topology. Two cell phones can synchronize directly via Bluetooth, three replicas can fit together in a mesh, and the result is the same as with a server coordinating everything. The server, when it exists, becomes just a convenient relay, not an authority.

This changes the nature of the application. The user does not wait for a network response to see their edit applied, because the local truth is already valid. The sync happens in the background and never comes back saying "your work has been discarded". It's what makes the app experience as modern collaborative editors so fluid, and it's the technical foundation of any serious local-first architecture.

The CRDT flavors you will find

Two major styles dominate. State-based CRDTs exchange the entire structure between replicas and use a merge function to combine. They are simple to reason, but heavy on the network when the data grows. Operation-based, or op-based, propagate only individual changes, which is more economical, but requires a reliable operations delivery layer.

Above these styles there is a catalog of ready-made types. Counters that add increments from multiple replicas without losing any. Sets that know how to mix additions and removals in a coherent way, such as OR-Set. And the most coveted case, sequential text, where each character receives a unique and sortable identifier so that competing insertions do not run over each other. Algorithms like Yjs and Automerge package all of this into libraries that you use without reimplementing the theory.

The good news for architecture decision makers is that you rarely write a CRDT from scratch. You choose the library, model your data on the types it offers and get convergence as a gift. The intellectual work is in mapping the domain to these structures, not in proving theorems.

Where CRDTs really shine

They are unbeatable when the merge rule is genuinely neutral, i.e. when keeping both edits is always the correct behavior. Collaborative text is the perfect example: if two people type in different paragraphs, you want both paragraphs, period. Lists, kanban boards, notes, vector drawings, and most collaborative productivity tools fall into this category.

They also shine in scenarios where connectivity is poor or intermittent in nature. Field applications, data collection in remote areas, devices that spend hours offline. In offline-first applications, CRDT is what allows you to work with complete confidence that nothing will be dropped in the next synchronization. Automatic convergence is exactly the guarantee that these contexts require.

And they shine when you want to eliminate the server from the critical path. Peer-to-peer architectures, local meshes, synchronization between devices belonging to the same user without going through the cloud. All of this is viable because the merge intelligence lives in the data, not in the infrastructure.

Where they are not the right answer

Here's the part that often gets swept under the rug. CRTDs converge to a valid state, but not necessarily to the state your business considers correct. Convergence is not synonymous with satisfied business rules. If two people book the last seat on an offline flight, CRDT will happily merge both reservations, and you'll have a mathematical guarantee of overbooking.

Conflicts that require semantic decision do not belong in CRDT. Balance that cannot be negative, uniqueness of a field, approval that invalidates another, any invariant that needs a "no, that cannot happen" wants a real arbiter. In these cases, the business rule needs to decide the conflict, and trying to push this to the data layer produces subtle and expensive bugs.

There is also the cost of memory and storage. To ensure convergence, many CRDTs store metadata that grows with the edit history. Removed item tombstones, per-character identifiers, version vectors. Without compaction strategies, a seemingly small structure can swell to surprising extents. Not every problem becomes CRDT cheaply, and not every problem should.

My recommendation as a CTO is pragmatic. Use CRDT where the merge is naturally additive and the experience gain is real. Where correctness depends on a business invariant, accept an arbiter, be it a server, a command queue, or an explicit resolution flow presented to the user. The most common mistake is to treat CRDT as a silver bullet and discover overbooking in production.

If you're designing the sync layer of a local-first product now, it's worth clearly separating what's auto-mergeable from what needs human or server decision-making before choosing the tool. This honest division will save months of rework.

Also read