There are two ways to build real-time collaboration - either everything goes through a central server, or you go for a P2P mesh. Assume a collaborative canvas, like Figma, Canva, or Miro, with 10 users …
When you route every cursor movement through a central server, 10 users generate 60 pointer updates each second, which means 600 messages arriving at the server, which then fans them out to 9 recipients each. That is 5,400 messages per second, per session, just for mouse tracking.
The alternative is a P2P mesh - every client connects directly to every other client, and the server never touches these high-frequency packets at all.
But the mesh has its own problem - connections grow as n × (n - 1) / 2. With 4 users, 6 connections. With 10 users, it is 45. With 20, it becomes 190. i.e., each individual browser holds open (n - 1) simultaneous WebRTC connections. The server load goes to zero, but the client complexity grows quadratically.
So when does mesh make sense?
Use mesh topology when the data is high-frequency, low-stakes, and latency-sensitive - cursor positions, live selections, drawing strokes. Losing one update is fine; the next one arrives in 16 ms anyway. The server genuinely adds no value in this path.
Do not use it for writes that matter - document saves, access control changes, conflict resolution. Those still go through the server. A better way to think about mesh topology is as a way to offload a specific class of traffic.
Here’s something worth remembering - not all real-time data is the same.
Cursor positions and committed state have completely different requirements. Treating them identically - routing both through the server - is what creates the bottleneck in the first place. Split the traffic by its tolerance for loss and latency, and the architecture becomes obvious.
Hope this helps.