Use YJS as main data structure

Hi, we’ve implemented Yjs on top of Slate, with a custom version of y-websocket, and so far so good :slight_smile:

We’re now considering if it would make sense to use Yjs not only for the text editor content, but for any data we load in the application, since the collaborative use case goes beyond writing.

A user would log into a workspace, and would load text documents with metadata, and other JSON-formatted objects. All of this can be edited and needs to be synced between clients.

The reason why we are thinking about using Yjs for the other data types, is that it would solve the case where the app works offline, and needs to sync up later and merge conflicts, exactly like with the editor.

Is using Yjs outside of text editing overkill?

If no, would it be a good idea to use one YDoc per workspace, with subdocs for every item? I’ve read from other posts that we’d need to extend y-websocket to support multiplexing on subdocs.

I also wanted to know what’s the status on the new y-websocket refactoring, and if it would be suggested to wait until then before using it in production.

Thanks!

1 Like

I don’t think so at all! Yjs is fantastic for syncing in the general case:

  1. It’s fast
  2. It handles basic data types like Y.Array & Y.Map, and these data types are composable
  3. It removes the need to have an intervening API, which reduces a LOT of boilerplate state sync code

I made a little library that shows some of its potential when coupled with svelte: https://svelt-yjs.dev/

I’ve also used Yjs to sync state in a browser-based 3D world meant for collaborative creation & community called https://www.relm.us

The only “down side”, in general, that I know of is the story for permissions. It’s difficult to get the same ease of use in combination with distributed access & edit permissions. I’d love to know if anyone has solved this in an elegant and/or general way.

1 Like

This is super interesting, and congrats for the project!

The way I understand it, the client would have one websocket connection, one main Y.doc with the state of the client for that user, and you then apply all changes to this main Y.doc, potentially using lazyloaded subdocs to avoid transmitting everything at once?

For permissions, the main problem I see is that (as far as I understood), you can’t slice a Y.Doc and only get a piece of it (e.g. if the main Y.Doc is the entire state, you would want to slice an array of subdocs based on read/write access at the server level, before transmitting it).

I guess for now this is a roadblocker, since we would heavily need permission-based access, but looking forward to hear more thoughts about it.

Hi @kappa90,

Is using Yjs outside of text editing overkill?

My intention is to make Yjs a data storage for any kind of application. So no, it is not overkill. But as a user, you have to realize that this is a completely new way to build applications. There is relatively little experience and tooling for this use-case. As a framework for syncing application state Yjs would be competing with Derby and Firebase/Firestore. This is why I am focusing on the collaborative-editing use-case at the moment (which is an almost uncontested market). However, there are awesome success stories of companies that represent very complex data structures with Yjs - e.g. Relm and Legendkeeper.

If no, would it be a good idea to use one YDoc per workspace, with subdocs for every item? I’ve read from other posts that we’d need to extend y-websocket to support multiplexing on subdocs.

This is really up to you and depends on the specific application. I recommend to experiment with this and fragment the data into separate subdocuments whenever it makes sense. I also recommend to handle permissions using subdocuments. Subdocuments are really just links to other Yjs documents. It is pretty complicated to implement complex permissions for a single document (e.g. user A can write in a certain part of a document, but another section of the document is read-only). Rather you should assign “read-only”, “read-write”, and “unauthorized” permissions to specific (sub)documents and ensure on the server that only users with “read-write” access can apply changes to a specific (sub)document.

I also wanted to know what’s the status on the new y-websocket refactoring, and if it would be suggested to wait until then before using it in production.

I’m slowly realizing that a refactor of the y-websocket backend will be a ton of work, because I want to provide a generic backend solution that can be nicely integrated into existing applications. I’m currently working on the Yjs Rust port and will come back to the server after that (in a couple of months). It is very likely going to be a separate project that is compatible with y-websocket.

In any case, you probably want to build your own y-websocket backend if you care about subdocuments and permission handling.

Thanks @dmonad, this explains a lot!

I think for now we’ll keep the current infrastructure. For collaborative editing alone, Yjs is already top-notch, a giant kudos and thanks for bringing this to life.

1 Like