What it took to move a collaborative browser IDE beyond process memory
The first collaboration model in CodeVerse was convincing in exactly the way a local demo needs to be convincing. Open two tabs. Join the same room. Type in one editor. Watch the other editor update. Then ask one unpleasant question: what happens when those two sockets land on different server instances? The answer was that the room stopped being a room. Each process had its own memory, its own presence list, and its own idea of the current files. A restart erased state. A reconnect could create a second identity. A load balancer could turn a working demo into two isolated conversations. This article is about the work that followed: moving CodeVerse from synchronized tabs to a collaboration path I could test across processes, recover after disconnects, and describe without pretending a local benchmark was a production capacity claim. The real boundary was not Socket.IO Socket.IO made connection handling and room fan-out approachable, but it did not decide where truth lived. That distinction matters. A room name inside one Socket.IO process is a routing convenience, not durable shared state. Once I wanted multiple application instances, I needed separate answers for four kinds of information: Document state — the convergent contents of every file. Room policy — organizer identity, edit permissions, active file, and revision. Presence — which sockets are here now, on which instance, with which effective role. Durability — what survives Redis expiry, application restarts, or a longer period of inactivity. CodeVerse now uses Yjs for convergent document updates, Redis for live distributed room state and pub/sub, and Supabase for durable room snapshots and membership data. Socket.IO remains the transport and fan-out layer. That separation was more important than any individual library choice. Redis does three different jobs It is easy to say “I added Redis” and leave the architecture vague. In CodeVerse, Redis has three explicit responsibilities. 1. Cross-instance fan-out