CRDTs are hard

Table of contents

YJS

YJS has the greatest community and contributor support. It’s also one of the oldest implementations. It’s also lightweight, at ~26Kb. Most people stop here.

Pros:

Cons:

Automerge

Automerge offers a very convenient JS-first API. It maps the JS shapes you give it to reasonable CRDT types.

Pros:

Cons:

Loro

Loro is a fairly new Eg-walker implementation with rich text.

Pros:

Cons:

Collabs

Collabs allows strongly-typed primitives with custom merge strategies.

Pros:

Cons:

CRDTs are hard

Ugh, none of these implementations support preserving merge history AND linking between documents AND have a reasonable bundle size. Guess it’s time to make my own! I only really need rich text.

Let’s look at plain-text merging first. FugueMax is the best algorithm and has a few variants. But it’s pretty complicated. Then for preserving history we need to save a log of operations. To identify merge conflicts we need to give those operations identifiers and store them in some kind of causal graph. Finally we can use FugueMax, but we do have to temporarily “undo” and “redo” nodes as we walk the tree.

Oh, and for any of these to perform reasonably you’ll need to encode runs to save on memory.

I just described Eg-walker, and it’s not simple at all. I’ve implemented it a couple times, and it requires complex graph types to perform well.

Conclusion

I don’t think I’ll be using CRDTs for anything besides live shared editing. I’ll stick to traditional source control algorithms for user annotations.