CRDT in production, how to handle protocol versioning?

I’m working on a side project, for which I want to save on cost as much as possible. Using CRDT without relying on a central server seems to be a cost effective approach, however I’m concerned about protocol changes or data structure changes/mismatches when users use different client versions.

For example, initially, my app uses a CRDT datastructure called the version 1. Then for the next release, I changed the datastructure to version 2. Now some of the users use the new app, while others use the old app, the CRDT datastructures mismatch. I wonder how an real app should handle this situation?

I understand this is beyond the scope of Yrs/Yjs, however I wonder if anyone who has used CRDT for production has previously dealt with a similar situation?

Thanks

I have dealt with it by using a “documentVersion” field somewhere in the document to indicate which protocol version the document adheres to (an integer value). When loading the document on client (in my case, server), you can run any missing “migrations” on the document based on the version number, in a similar way that database migration tools like Flyway do. I’ve been very happy with this approach.

but say you have 2 clients, one generates a document diff of version 2, one generates a document diff of version 1, how do you merge them into your document. do you allow the version field to be overwritten by lower version number?

You only go up. When you load a doc, you run migrations upwards. If doc has the latest version you don’t run migrations. Like db migration tools do. If you see a doc with a higher version than you are aware of, you know the client code is out of date (or data is corrupted).

But this is not bulletproof as there’s no guarantee that an older client does not mess up the doc after a migration. Another way would be to write idempotent migrations that you can repeatedly run in case you need to repair a doc. Something like that.