[HN Gopher] An interactive intro to CRDTs
       ___________________________________________________________________
        
       An interactive intro to CRDTs
        
       Author : jakelazaroff
       Score  : 595 points
       Date   : 2023-10-04 13:12 UTC (9 hours ago)
        
 (HTM) web link (jakelazaroff.com)
 (TXT) w3m dump (jakelazaroff.com)
        
       | braden-lk wrote:
       | I've built a successful business from a TTRPG campaign manager
       | (LegendKeeper) using CRDTs, specifically the Yjs kind. It's been
       | great, and the UX of CRDT-powered stuff is excellent. Zero
       | latency, eventually consistent; overall users love the
       | performance and offline capability.
       | 
       | That said, there are a lot of trade offs. Some things that are
       | easy in a traditional server-client model become difficult in the
       | local-first context that CRDTs provide. Role based authorization
       | is hard, data model changes must be done additive (never
       | mutative), and knowing what state a client is in when debugging
       | is tough too, without a lot of "full-surveillance"-level tooling.
       | Also with the automatic , bidirectional syncing a lot of CRDT
       | architectures afford you, a bug in production that corrupts data
       | can virally propagate and cause a huge headache.
       | 
       | Investor-funded services like Liveblocks are starting to pop up
       | that promise to make this stuff easier, but as an indie I find
       | them expensive; I'm sure they're a great value for big corps or
       | funded teams though. Rolling my own infrastructure for Yjs has
       | been taxing, but I've learned a lot, and have been able to tailor
       | it exactly to my needs.
        
         | janesconference wrote:
         | How does it scale? What happens if you have many users or a
         | bunch of users with huge history on their data? If you haven't
         | hit these limitations, what do you plan to do when (if) you hit
         | them?
        
           | braden-lk wrote:
           | I don't know how well the original y-websocket provider
           | scales, as it holds ydocs in memory. I imagine lots of folks
           | are using it just fine in production, though. I wrote a less-
           | stateful version of y-websocket that uses the Yjs
           | Differential Updates API to save and serve updates without
           | loading the docs into memory.
           | 
           | As long as you have garbage collection turned on for your
           | Ydocs, they stay pretty small, especially if you are avoiding
           | using YMaps. (The strings that serve as YMap keys can't be
           | GC'd, from what I understand. YMaps are great for bounded
           | domain objects, but not so great for storing collections,
           | dictionary-style. Y-KeyValue solves this problem.)
           | 
           | I eventually added a X MB document size limit on the backend,
           | but only after doing a statistical analysis on existing
           | documents. I found a size threshold that was a strong
           | indicator of abnormal/buggy behavior, and set a limit under
           | that. Without the limit, occasionally I had huge Ydocs,
           | usually created by a bug or weird user behavior, clogging up
           | database resources. Now I block those ydocs on the backend
           | and send a messsage to the user with some mitigation/recovery
           | tips. I plan to add automatic document repair, but just
           | haven't gotten to it yet. As LK matures and I get better with
           | Yjs, these bugs become much rarer.
        
         | doctorpangloss wrote:
         | > data model changes must be done additive (never mutative)
         | 
         | Sounds painful. It means your mutative data model changes,
         | which exist, live somewhere else.
        
           | braden-lk wrote:
           | Yep, though coming from mobile development this was somewhat
           | familiar. A lot of mobile apps are local-first, but I don't
           | think it was called that back when I was doing mobile. Most
           | mobile platforms expect this and provide tools to ease
           | migrations, like Room on Android. Since CRDT approaches are
           | still fresh, I imagine most people are rolling their own
           | adhoc migration strategies. Ink & Switch is working on this:
           | https://www.inkandswitch.com/cambria/
        
         | Karrot_Kream wrote:
         | Is LegendKeeper built on top of the Websocket Yjs provider? If
         | so, do you run the Websocket server yourself? If not, do you
         | use WebRTC and have you had any STUN/TURN issues with that?
         | 
         | LegendKeeper looks really awesome btw, I might bring this up
         | for my own campaign use. I've been thinking of using Yjs to
         | build some character sheet builders myself which is why I'm
         | asking.
        
           | braden-lk wrote:
           | I built a custom solution based on y-websocket that handles
           | multiplexing and syncing multitudes of Ydocs at once; a
           | single YDoc is not really enough for complex apps. I run the
           | server myself; originally on GKE because I was learning it
           | for work, but then once I went FT on LegendKeeper, k8s became
           | super-overkill minus the learning context. Finally switching
           | to Render after tiring of fighting weird K8s internal DNS
           | issues.
        
         | paulgb wrote:
         | > knowing for sure what state a user's client is in when
         | debugging is tough too
         | 
         | My team has built an open-source debugger for Yjs that might
         | interest you (docs: https://y-sweet.cloud/advanced/debugger)
         | 
         | You mention the investor-funded services that pop up to make
         | this stuff easier -- our goal with Y-Sweet is to build the same
         | type of DX you'd get from those services, but build it on a
         | fully open-source (MIT) platform with Yjs at the core:
         | https://github.com/drifting-in-space/y-sweet
        
           | janesconference wrote:
           | A couple of questions about y-sweet, based on the experiences
           | I had with CRDTs:
           | 
           | 1) Does the server keeps in memory the "active" documents? In
           | other words, does the server need to open a document and keep
           | it in RAM while clients are connected to it (I assume there's
           | a websocket connection somewhere in the client that keeps it
           | hot)? Or is the server stateless - just connects to the store
           | when needed? I found the latter very hard to do.
           | 
           | 2) Does the client persist entries using indexeddb? If yes,
           | does opening many tabs cause redundant writes as they all
           | sync with the server? If not, does the client need to fully
           | re-sync with the server anytime it wakes up?
           | 
           | 3) Is it possible to observe updates on the client as they
           | come? One of the major use cases of CRDTs is to index data on
           | the client - then you can have a dumb server that just syncs
           | data between clients and a smart client that does search,
           | graphs, visualizations etc. on the data it receives. To do
           | that, the client needs to observe updates one by one and
           | process them to create secondary indexes. Is it possible to
           | do with y-sweet without forking its source code? I remember
           | getting updates yn Y.js being quite inefficient as you need
           | to replay them all or something similar, but that was a
           | couple of years ago.
        
             | paulgb wrote:
             | Good questions!
             | 
             | > 1
             | 
             | The server keeps the documents in memory when they are
             | open, but it is horizontally scalable by hosting using
             | CloudFlare Durable Objects. (We also plan to support
             | Plane.dev but that's not built out yet).
             | 
             | > 2
             | 
             | The client is based on Yjs, so it's compatible with Yjs'
             | y-indexeddb provider to store in IndexedDB. Tabs
             | synchronize state between each other using a local
             | broadcast channel. The client only synchronizes unsynced
             | state with the server, so if one tab has already pushed the
             | local offline edits to the server, the other tabs can
             | discover that and avoid pushing them. That said, I'm not
             | 100% sure if Yjs deals with the race condition where two
             | tabs wake up at the same time so the server has not yet
             | received offline edits from either, I'd have to check on
             | that.
             | 
             | >3
             | 
             | Yes, Yjs types have an `observe` method that takes a
             | callback, which receives an event with details of each
             | edit. Here's an example for observing events of a Y.Map:
             | https://docs.yjs.dev/api/shared-types/y.map#observing-
             | change...
        
               | janesconference wrote:
               | Thanks! Re: 1, the docs are not really deep on that, but
               | from your answer it seems it possible to self-host
               | y-sweet on Cloudflare workers (I guess) with Durable
               | Objects as storage? Also, if you guys are going to have a
               | paid plan, how do you see the prices going? Comparable
               | to, say, Supabase per user, less or more?
        
               | paulgb wrote:
               | Sorry about that, I'll clarify the docs. You can self-
               | host on Cloudflare, but the storage is
               | R2/S3/S3-compatible blob storage.
               | 
               | Our tentative pricing is $25/month + $10/10k minutes of
               | "open connection" time (per-document, not per-connection,
               | so multiple users with the same doc open are not double-
               | counted). Storage is free if you bring your own R2/S3
               | bucket, or a nominal fee if you use ours.
               | 
               | Unlike supabase we don't do any of the relational stuff,
               | but for Figma-like apps where a lot of documents are
               | never touched, I think our hot/cold storage model can be
               | significantly cheaper at scale than a hosted postgres
               | database like supabase.
        
           | braden-lk wrote:
           | Ooh hell yeah; excited to check this out.
        
       | auggierose wrote:
       | I swear, HN somehow tracks what I am doing. The last few days I
       | also looked into CRDTs, Automerge, etc, and here we go. Happens
       | so often, it is uncanny.
       | 
       | Here is a good overview article, which has pointers to other
       | articles: https://cacm.acm.org/magazines/2022/11/265835-research-
       | for-p...
       | 
       | To me it seems that while state-based CRDTs are easy to
       | understand, operation-based CRDTs are actually what is used in
       | practice. Furthermore, it seems to me the difference between
       | operation-based Automerge, and operational transform (OT) is
       | actually not that big.
        
         | yawnxyz wrote:
         | I hadn't thought or heard about CRDTs for many months until
         | stumbling across Automerge yesterday. And here we are!
        
         | kortex wrote:
         | Have you heard about the Baader-Meinhoff phenomenon before? You
         | will now.
         | 
         | https://en.m.wikipedia.org/wiki/Frequency_illusion
        
           | codeulike wrote:
           | I just read about that yesterday
        
         | alephnan wrote:
         | It's also possible that the cycles of tech employment means
         | programmers are exploring similar topics over time.
        
       | splashdown5 wrote:
       | We used CRDTs to build Pennant notebooks (think Jupyter Notebooks
       | with collaborative Google Docs features https://pennant-
       | notebook.github.io/). Getting Yjs to behave for a multi-editor
       | environment took some doing. I highly recommend building your own
       | interface/library for interacting with Yjs and never touching Yjs
       | directly in React itself. The state management and event handler
       | cascade can be incredibly fussy if you don't have a good handle
       | on the whole system.
       | 
       | We've found most multi-user apps running over websocket
       | experience significant degradation in performance in the high
       | teen and low twenties. Beyond that we were able to update nested
       | CRDTs and all presence/user data in one connection with the
       | backend.
       | 
       | TipTap has a great backend called HocusPocus with well documented
       | API. Y-websocket backend is already quite good but the support
       | for user tokens isn't there natively. We were actually able to be
       | backend provider agnostic for well into the project. It's a fun
       | ecosystem.
        
       | kruhft wrote:
       | Relevant: http://burton.samograd.ca/Blog/the-eth-papers--
       | 2022/eth0004-...
       | 
       | My take years ago on a simple ERC-20 token (source) for a
       | "SpaceX" (sic, should have been SpaceBit) token.
       | 
       | Pretty obvious name though.
        
       | raybb wrote:
       | Seems like your blog isn't working on Mastodon right now?
       | 
       | https://mstdn.social/@blog@jakelazaroff.com
        
         | jakelazaroff wrote:
         | Hm odd, it works on mastodon.social --
         | https://mastodon.social/@blog@jakelazaroff.com
         | 
         | Will look into it, thanks!
        
       | infogulch wrote:
       | Martin Kleppmann gave a great talk about text editing CRDTs at
       | Strange Loop last month:
       | 
       | https://www.youtube.com/watch?v=Mr0a5KyD6BU | HN Submission:
       | https://news.ycombinator.com/item?id=37770541
        
       | angelmm wrote:
       | I love interactive introductions to complex topics. They are the
       | best way to learn and consolidate their concepts. Great resource!
        
       | ChrisMarshallNY wrote:
       | Thanks, Jake. That's nicely done.
        
       | zubairq wrote:
       | One of the best CRDT tutorials I have tried, well done!
        
       | ooterness wrote:
       | For reference: CRDT = Conflict-free Replicated Data Type
       | 
       | https://en.wikipedia.org/wiki/Conflict-free_replicated_data_...
        
         | uxp8u61q wrote:
         | It's the first sentence under the heading "What is a CRDT?" in
         | the linked article.
        
           | aierou wrote:
           | Frankly, it needs to be in the very first sentence of the
           | article. Acronyms Seriously Suck.
        
       | rahimnathwani wrote:
       | I love that, on a phone with multi-touch, you can draw on both
       | canvases at the same time.
        
       | totetsu wrote:
       | What's the font on the code snipits? Asking for a friend.
        
         | denvaar wrote:
         | I know, right? I just bought it.
        
         | lelandfe wrote:
         | Cartograph CF: https://connary.com/cartograph.html
        
           | [deleted]
        
       | danielvaughn wrote:
       | This is absolutely lovely, well done. I've worked with CRDT's a
       | couple times and it's always mind-bending trying to understand
       | the data flow; these interactive demos make it so much clearer.
        
       | bafe wrote:
       | Thank you, very cool work. A small note: the first example
       | doesn't work on mobile devices. If I drag, it will just scroll
       | the page instead of drawing
        
       | thoughtlede wrote:
       | I have studied CRDTs at a deeper level for a few weeks and
       | implemented several small prototypes. They are fascinating. As an
       | eventual consistency model for data management, CRDT inspired
       | techniques (op-based or state-based) are useful.
       | 
       | However, for building user-facing applications with CRDTs, their
       | importance is unclear.
       | 
       | The question with CRDTs and local-first paradigms has always been
       | the pressing need (or the lack thereof). The only one plausible
       | 'need' that CRDTs serve is real-time collaboration and that too
       | with a squinting eye.
       | 
       | Real-time collaboration support translates, in practice, to text-
       | editing and picture-editing collaboration. Google docs and the
       | ilk have solved that problem (using central solutions). A CRDT-
       | inspired central-solution like Figma is inspiring, and maybe
       | that's the only place CRDTs fit in their survival quest when
       | combating against central-solutions.
       | 
       | The rest of the claimed advantages seem to not withstand the test
       | of times. This articles talks about 7 features of CRDTs [1].
       | 
       | Fast: Things are already fast with central solutions.
       | 
       | Multi-device: There is multi-device support with almost all
       | solutions (if you decouple the real-time collaboration aspect).
       | 
       | Offline: It's rare, at least in first world countries, to be in a
       | need for offline access (except maybe in airplanes).
       | 
       | Longevity: As can be seen from another comment here, longevity is
       | actually a problem with CRDTs because data model updates are not
       | easy.
       | 
       | Privacy: With BYOK encryption pattern, privacy is not as much an
       | issue.
       | 
       | User control: Even with CRDTs, user is not in control of their
       | data - other peers can mess with your data.
       | 
       | [1] https://www.inkandswitch.com/local-first/
        
         | ochiba wrote:
         | I agree. We had similar conclusions around the implementation
         | of PowerSync (sync engine enabling offline-first applications).
         | Instead of CRDTs we went with the architecture of a central
         | server authority and a form of server reconciliation [1] for
         | consistency.
         | 
         | [1] https://www.gabrielgambetta.com/client-side-prediction-
         | serve...
        
       | jimmySixDOF wrote:
       | Big shout out to tldraw and whatever they do under the hood to
       | keep it as lightweight and open to integrations - it just handles
       | a tonne of content in group sessions without complaining somehow
       | it's like the perfect mix of simplicity and power features.
        
       | [deleted]
        
       | matlin wrote:
       | Evan Wallace (co-founder of Figma) has one of the best
       | visualizations of CRDTs in action
       | https://madebyevan.com/algos/crdt-fractional-indexing/
       | 
       | In practice, most apps will only need Last-Writer-Wins registers
       | and not the more complicated sequence CRDT's that you find in
       | Y.js and Automerge.
       | 
       | We've built a auto-syncing database that uses CRDTs under the
       | hood but never exposes them through the API. So if you want all
       | of the benefits of CRDTs e.g. offline-first user experience,
       | checkout our project, Triplit!
        
         | danielvaughn wrote:
         | Yep. I figured this out the hard way. Spent a year or so
         | investigating CRDTs before I came across Figma's blog post and
         | realized they fit my use case exactly, and I really didn't need
         | to bang my head against the desk for so long because the
         | solution actually isn't so bad for tree-based editing.
        
         | jakelazaroff wrote:
         | Author here -- Evan Wallace's visualizations were a big
         | inspiration!
        
       | insanitybit wrote:
       | So far this is probably the best "intro to CRDTs for a
       | _developer_ " I've read. I built a product around CRDTs,
       | essentially, and my god was it painful trying to engage with.
       | Showing actual code, explaining that `merge` is the fundamental
       | operation, etc, is really all a developer needs to know IMO.
       | 
       | Also, the fact that we always use text editing as the de-facto
       | solution is so weird to me since that problem is both niche and
       | extremely complex. IMO a better example would be something like
       | "Can this person drink alcohol?". Age moves in one direction so
       | it has a simple merge function:                   def
       | set_age(self, new_age: int):             self.age = max(self.age,
       | new_age)
       | 
       | A property of this is that if I query your age and if you're 21 I
       | can cache that age forever. You'll only ever be >= 21, after all.
       | If I add new queries that care about you being 25 (for a hotel) I
       | can satisfy the "drinking age" queries from a stale cache and
       | then retrieve the true value (<25) when I need to check if you
       | can book a hotel.
       | 
       | This means you can have distributed caches without invalidation
       | logic. A pretty amazing property since cache invalidation is a
       | hugely complex problem and has seriously negative performance/
       | storage implications.
       | 
       | It also means you can drop writes. If my system gets information
       | that a person was 18, but that information is out of date, I can
       | drop that write, and I can do so by examining the cache and
       | viewing _stale_ information, only checking the real value if the
       | cache value is  < 18.
       | 
       | This whole thing lets you push computation to the edge, drop
       | expensive writes, ignore any cache invalidation logic, cache
       | values forever, potentially answer queries from stale cache
       | values, etc.
       | 
       | Anyway, kudos for the writeup. I skimmed the second half but the
       | first half was great and the second half looked legit.
        
         | hmottestad wrote:
         | I really like this somewhat old video by Microsoft
         | https://www.youtube.com/watch?v=oyUHd894w18 it was my first
         | intro to CRDTs.
        
         | steve_adams_86 wrote:
         | The way you describe that makes me wonder if state machines
         | would be natural tools to express CRDT "states".
        
           | insanitybit wrote:
           | The important this is that, as mentioned in the article, you
           | need to have a way to converge states in a way that obeys
           | certain properties.
        
             | steve_adams_86 wrote:
             | Yeah, as I'm reading this more thoroughly I see that there
             | wouldn't be many states to express, and the merging itself
             | isn't something you'd express in states.
             | 
             | I initially thought more of the inner workings could be
             | managed this way, but it seems better implemented as it is
             | in the article.
        
               | insanitybit wrote:
               | You should check out the P language and consider the
               | implications of CRDTs on the `machine` constructs :)
        
         | alephnan wrote:
         | > text editing as the de-facto solution is so weird to me since
         | that problem is both niche and extremely complex.
         | 
         | My first foray into collaborative editing was for my text
         | editor. Indeed, things get super linearly harder as you add
         | basic functionality of editors such as deleting and replacing,
         | especially when those space multiple lines.
         | 
         | Instead, I reached for Fraser's differential syncing.
         | https://neil.fraser.name/writing/sync/. There's a lot of
         | ambiguity and nuances in various versions of the prose and
         | white paper that I could never really flesh out.
         | 
         | I think anyone attempting to relay a collaborative editing
         | algorithm needs to do is start with the simplest scenarios:
         | append only / monotonically increasing data.
        
         | richardwhiuk wrote:
         | Somebody typos there age to be too high, and then you cache it
         | forever.
         | 
         | You have to be careful here.
        
           | LtdJorge wrote:
           | And of course you _typoed_ there instead of their :D
        
           | insanitybit wrote:
           | Of course. All things require care. Not all problems fit into
           | CRDTs either.
        
         | kevincox wrote:
         | > the fact that we always use text editing as the de-facto
         | solution is so weird to me since that problem is both niche and
         | extremely complex
         | 
         | The reason we use that is because it is complex enough to show
         | the problems that CRDTs solve. I would argue that this painting
         | example is too simple. The core merge loop is:
         | if pixel.created_at < newPixel.created_at {             pixel =
         | newPixel;         }
         | 
         | this is maybe good as a first step, but I don't think it is
         | enough to even really called an "Intro". A last-write-wins
         | register is trivial.
         | 
         | Simple text inserts with a simple "insert after" CRDTs is not
         | much more complicated but involves things like generated unique
         | IDs without communication and how to resolve conflicts with
         | some sort of globally consistent ordering.
        
         | cabalamat wrote:
         | > Age moves in one direction so it has a simple merge function:
         | 
         | Better to use date of birth as that doesn't change at all.
        
         | whalesalad wrote:
         | I realize this is a straw man argument/example - but it feels
         | hairy to me. So much fuss about age and cache invalidation ...
         | age should not be persisted anywhere. When you make age a
         | calculated property from birthday it is never inaccurate or
         | stale or wrong. "set age" should not be a possible operation in
         | any system imho.
        
           | insanitybit wrote:
           | Even if you persist a timestamp like 'birth date' into a
           | database it doesn't matter - you can still cache the
           | resulting 'age' calculations as CRDTs. But yes, it is a made
           | up example. Another might be 'first/last observed time' for
           | an IP address.
        
             | rahkiin wrote:
             | For GDPR it is better to store 'is legal drinking age'
             | instead of age or forbid even the birthdate
        
               | neilellis wrote:
               | Until the legal drinking age changes :-)
        
               | rahkiin wrote:
               | Ideally you only verify at time of purchase and do not
               | care afterwards until next purchase. Bare minimum to hold
               | to laws
        
               | jcrites wrote:
               | Ideally you also don't need to verify it more than once,
               | though. Otherwise, it will be friction that detracts from
               | the user experience.
        
               | actionfromafar wrote:
               | That's why you need the SAAS, for compliance and i18n!
        
               | yard2010 wrote:
               | Fun fact: in some places in Canada the legal drinking age
               | is 19
        
               | insanitybit wrote:
               | I don't think we need to design the entire "can you
               | legally drink" SaaS, hopefully my example is clear enough
               | and people can leverage the _concept_ for more reasonable
               | circumstances.
        
       | yoyohello13 wrote:
       | [flagged]
        
       | [deleted]
        
       | endisneigh wrote:
       | CRDTs seem like one of these things that are mentioned on here
       | frequently, but I haven't seen that many popular apps that use
       | them. Any examples?
        
         | jamil7 wrote:
         | Apple Notes.
        
           | endisneigh wrote:
           | ah, very cool. TIL.
        
         | unholiness wrote:
         | Once you start adding enough complexity, there will arise cases
         | that the primitives are an awkward place for the merging to
         | happen. There will arise cases where that user expectations and
         | the merge function behavior don't agree. There will arise cases
         | where the server can do a better job than the client at
         | applying the change. There will arise cases where you need to
         | undo but the undo function violates the merge function. And as
         | the author freely states, there will arise cases where sending
         | the whole state is prohibitively slow.
         | 
         | Those are really only issues with state-based CRDTs. The
         | fundamental concepts behind operation-based CRDTs vs
         | operational transforms vs bespoke hybrid approaches aren't
         | really different. It's all about determining an unambiguous
         | order, then getting everyone to update their state as if it had
         | been applied in that order. Much less democratic but much more
         | practical.
        
         | euroderf wrote:
         | pijul version control is not yet popular but might become so.
         | 
         | https://pijul.org/manual/theory.html?highlight=CRDT#conflict...
        
           | kiitos wrote:
           | > In Pijul, there are two kinds of conflicts inside a file:
           | 
           | > When two different authors add lines at the same position
           | in a file, and it is impossible to tell which comes first in
           | the file.
           | 
           | > When one author adds a line in a block of text or code,
           | while another author deletes that block.
           | 
           | I don't think this is true. Two different authors can modify
           | the same line in different ways, which is a conflict that's
           | different than either of these categories.
           | 
           | > It is important to note that conflicts in Pijul always
           | happen between changes, for example we might say that "change
           | A conflicts with change B".
           | 
           | I also don't think this is true. Conflicts can occur in a
           | history (lineage, sequence, etc.) of concurrent changes,
           | which are different than the delta between any two
           | independent changes.
        
         | kitplummer wrote:
         | Ditto (https://portal.ditto.live and https://docs.ditto.live)
         | uses them.
        
         | tin7in wrote:
         | A lot of the popular document/notes/whiteboard apps would use
         | Yjs or Automerge or even a ready solution like Liveblocks.
        
         | c_s_guy wrote:
         | I've seen it come up often in collaborative text editors.
         | 
         | Also see: https://github.com/yjs/yjs
        
         | antidnan wrote:
         | The academic version of them is not used that widely AFAIK
         | outside of newer companies using Yjs.
         | 
         | I believe Figma, Notion, Google Docs, etc all use some form of
         | OTs which aren't necessarily a perfect CRDT
        
           | jitl wrote:
           | Notion doesn't use OT. Most things are last-write-wins, but
           | we have operations that merge like list re-ordering or
           | permission changes. Today our text is last-write-wins, but
           | we're developing a CRDT solution - if that sounds like
           | something you'd like to work on, shoot me an email
           | jake@makenotion.com or apply
           | https://boards.greenhouse.io/notion/jobs/5602426003
        
         | papercrane wrote:
         | Redis uses them in their enterprise products for active-active
         | distribution.
         | 
         | https://redis.com/blog/diving-into-crdts/
        
         | brigadier132 wrote:
         | They've only recently become practical.
        
         | cdmckay wrote:
         | I believe Notion uses them.
        
           | jitl wrote:
           | Notion doesn't use OT or CRDT in production. Most things are
           | last-write-wins, but we have operations that merge like list
           | re-ordering or permission changes. Today our text is last-
           | write-wins, but we're developing a CRDT solution - if that
           | sounds like something you'd like to work on, shoot me an
           | email jake@makenotion.com or apply
           | https://boards.greenhouse.io/notion/jobs/5602426003
        
           | endisneigh wrote:
           | really? you have a link to a blog post or something? last I
           | heard they explicitly did not use them.
        
             | ko_pivot wrote:
             | In production, they don't. This is evident when two users
             | try to edit the same block at the same time -- its last
             | writer wins right now, not merging. They have hired some
             | engineers to work on a CRDT text editor implementation
             | though.
        
               | jakelazaroff wrote:
               | No idea whether Notion uses CRDTs, but last writer wins
               | is a (naive) strategy for editing text. You can see this
               | in the article -- if you edit the LWW Map, for example,
               | even though the _keys_ are merged, each _value_ will be
               | taken from one peer or the other. Once you get to that
               | last "primitive" CRDT -- the register holding each map
               | value -- updates are atomic. So Notion may be using CRDTs
               | for e.g. the order of blocks in a page, but not (yet?)
               | using them to merge text.
        
           | auggierose wrote:
           | No, Notion uses OT (operational transform).
        
         | bunnybender wrote:
         | I believe Actual Budget, a local-first personal finance app
         | uses them.
         | 
         | https://github.com/actualbudget/actual
         | 
         | The original author has both written about and given
         | presentations about CRDTs.
        
         | auggierose wrote:
         | Is Figma popular enough?
         | 
         | https://www.figma.com/blog/how-figmas-multiplayer-technology...
        
           | danielvaughn wrote:
           | Figma's interesting because it's not strictly speaking a
           | CRDT. It borrows heavily from some of the CRDT ideas, but
           | it's really an editable tree where most changes are atomic
           | and thus use a last-writer-wins approach. That, and re-
           | ordering tree nodes uses fractional indexing.
        
             | auggierose wrote:
             | Yes, I think most practical solutions are not strictly
             | CRDTs, not even Automerge, I think.
        
               | Rapzid wrote:
               | Automerge is interesting as it's an op-based CRDT system
               | vs state-based.. This should make use cases involving a
               | central authority easier to work with but.. Their docs
               | lack any detail useful to taking advantage of this haha.
        
               | wim wrote:
               | Right, there are quite some collaborative applications
               | for which a hybrid approach is useful. We're building a
               | collaborative editor (https://thymer.com) for example,
               | where the underlying data structure is also a tree (as
               | the text documents also support outliner-like features,
               | so a flat list of characters/lines isn't enough). To
               | avoid tree conflicts, insert and move operations look
               | more like OT than CRDT however, where other updates can
               | use a simple CRDT mutation.
        
         | paulgb wrote:
         | Modyfi.com built a raster image editor on Yjs[1]
         | 
         | [1] https://digest.browsertech.com/archive/browsertech-digest-
         | ho...
        
         | flatline wrote:
         | Google docs, really any online collaborative editor uses them.
         | If you have a distributed system with multiple asynchronous
         | data feeds into the same sink, this is one way of automatically
         | resolving conflicts. A complicated way that most applications
         | probably don't really need, and that does not guarantee
         | consistency. But they are neat.
        
           | rubatuga wrote:
           | Source? Heard Google Docs stopped using CRDT.
        
           | papercrane wrote:
           | I'm pretty sure Google Docs use Operational transformation
           | (OT). Google Docs pre-dates the paper that defined CRDTs.
           | It's certainly possible they've updated their algorithms
           | since then though.
        
       ___________________________________________________________________
       (page generated 2023-10-04 23:00 UTC)