Crdts: Convergence Without Coordination
Posted3 months agoActive2 months ago
read.thecoder.cafeTechstory
calmpositive
Debate
20/100
CrdtsDistributed SystemsCollaborative Editing
Key topics
Crdts
Distributed Systems
Collaborative Editing
The article discusses Conflict-free Replicated Data Types (CRDTs) and their application in distributed systems, sparking a discussion on their use cases, implementations, and potential extensions.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
7d
Peak period
31
Days 7-8
Avg / period
11
Comment distribution33 data points
Loading chart...
Based on 33 loaded comments
Key moments
- 01Story posted
Oct 16, 2025 at 11:00 AM EDT
3 months ago
Step 01 - 02First comment
Oct 23, 2025 at 10:39 AM EDT
7d after posting
Step 02 - 03Peak activity
31 comments in Days 7-8
Hottest window of the conversation
Step 03 - 04Latest activity
Nov 2, 2025 at 2:35 PM EST
2 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45606224Type: storyLast synced: 11/20/2025, 6:24:41 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
The article then goes into some examples of CRDTs and their merge operation, and the examples are pretty straightforward: take the maximum of two values, or take one with a more recent timestamp, etc.
But what about the motivating example? What should a merge function do with the inputs "change the third word from 'affect' to 'effect'" and "delete the third word"? In other words, how does the function know which of these operations "wins"? It could ask a user for a manual resolution, but is there a reasonable way for a function to make this determination itself? Maybe deletes are more powerful than word changes, so the delete wins.
For words, if a word is a single unit in your system, delete obviously beats amendment.
Hmm, last update as it's received by a central server? Last update according to the time on the device doing committing the update? The rabbit hole just keeps going, for each decision you get multiple new edge cases with unintended behavior...
And all but the last one fundamentally have lots of edge cases with e.g. high-latency sync
This is why I like using granular data structures where each value can be updated in an all-or-nothing manner and if one person's change overwrites another, the person whose change was overwritten will just assume that the other person made an update shortly after and the amount overwritten is minimal.
I.e., if there's a tricky conflict, the app need not resolve it at all. Rather, it should provide, by default, a nice way for the user to manage the resolution as part of the normal workflow.
Or, phrased another way, conflicts aren't conflicts. Parallel, "conflicting" edits are simply a state of affairs that is inherent to the process, and are still reflected in the data structure after merging all edits.
How this would actually look would probably vary from domain to domain. But my general philosophy on this stuff is that if complexity is real and potentially important to the user, the software should expose the complexity and enable the user to manage it, not force a simplification that hides something important.
That tradeoff is fine for some things but not others. There's a reason why git et al require human intervention for merge conflicts.
The article is doing a classic bait-and-switch: start with a motivating example then dodge the original question without pointing out that CRDTs may be a very bad choice for collaborative editing. E.g. maybe it's bad for code and legalese but fine for company-issued blog posts.
If you have worked on problems like this, you're very happy to converge on the same state and have no expectation that multiple concurrent editors will be happy with the result. Or even that one of them will be happy with the result.
You wouldn't use this in a situation like version control where you have to certify a state as being acceptable to one or multiple users.
And there are different algos, for diamondtypes:
Once a character is seen by clients any delete of it wins, algos like diamond types reconstruct each clients stream.
So in the case of DT, effect is absolutely gone, two clients deleting the e and one client deleted the ffects, and they both started at the same causal slice, but the A is a good question. You might just end up with an A.
In the case of multiple inserts in the same position dt uses the client ids lexical sort for ordering to reduce text interleaving.
Other crdt approaches may be positional or last write wins, in which case you may end up with nothing.
Besides being an amazing project loro crdts documentation and blog covers a lot of this stuff and names the specific algos they use.
My experience of CRDTs is it rapidly descends into a question of defining if two things are in fact equal or merely look equal. i.e. if two people concurrently add "this is a new item" to a set did they create two separate items or the same thing?
(Deleting a word is just changing it from word to ~word~ with the option to render conflict free deletions as empty space.)
It is slow and inefficient, but can be done.
Still working on good blog posts to explain and introduce it though.
https://github.com/arcuru/eidetica
I dream about this.
As an aside, I find FugueMax to be amazing to solve interleaving issues.
I've found for collaborative editing fuguemax for resolving intraline edits and h-lseq for the lines themselves has been amazing.
https://loro.dev/blog/crdt-richtext