DEV Community

Cover image for How I Built Real-Time Collaboration for a Diagramming Tool
Martin Staufcik
Martin Staufcik

Posted on • Originally published at Medium

How I Built Real-Time Collaboration for a Diagramming Tool

When I started building Modeldraw, a collaborative diagramming platform, I knew real-time collaboration would be essential. Multiple users needed to edit the same diagram simultaneously without conflicts, see each other’s cursors moving in real-time, and have everything work seamlessly whether they were logged in or accessing via a shared link.

What seemed straightforward at first turned into one of the most complex technical challenges of the entire project. Here’s how I solved it.

The Requirements

Real-time collaboration needed to handle:

  • Concurrent change merging — When two users edit the same element simultaneously
  • Live cursor tracking — Showing where other users are working with smooth animations
  • Flexible authentication — Supporting both authenticated users and anonymous viewers with share links
  • Reliable synchronization — Ensuring diagram state stays consistent across all clients

SignalR vs. WebSockets: Choosing the Right Foundation

The first major decision was choosing between raw WebSockets and SignalR. While both enable real-time communication, SignalR provides crucial abstractions that saved weeks of development time:

Transport Flexibility

WebSockets only work when both server and client support them, and network intermediaries like proxies or firewalls can block the connection. SignalR automatically selects the best available transport method and falls back gracefully. Your application works reliably across different browsers, devices, and network conditions without manual fallback logic.

Developer Experience

With raw WebSockets, you manage connections, message formats, serialization, and reconnection logic yourself. SignalR’s hub model lets clients call server methods and vice versa, almost like regular method calls. This simplified mental model significantly reduced complexity.

Built-in Resilience

When WebSocket connections drop, you must detect failures and implement reconnection logic. SignalR handles automatic reconnection with customizable retry strategies out of the box.

Scalability Features

WebSockets require custom implementations for tracking clients and broadcasting messages. SignalR provides groups and broadcasting natively, making it trivial to send updates to all users viewing a specific diagram.

ASP.NET Core Integration

SignalR integrates seamlessly with ASP.NET Core’s authentication, authorization, and dependency injection systems. On the frontend, the @microsoft/signalr package provides a TypeScript-friendly API.

The decision was clear: SignalR would provide the foundation we needed.

Solving the Concurrent Edit Problem

The trickiest challenge was merging concurrent changes. When User A and User B both modify the same diagram simultaneously, the system needs intelligent conflict resolution at both the shape level and property level.

Here’s the merge logic I implemented:

Property Addition

If User A adds property P1 and User B’s save doesn’t include it, keep A’s addition. New properties from the first user are preserved.

Property Modification

If both users modify property P2, compare B’s value with the original. If B didn’t actually change it, keep A’s modification. This prevents one user from accidentally overwriting another’s intentional changes.

Property Deletion

If User A removes property P3 and User B tries to save with it, the deletion wins. This ensures cleanup operations aren’t reversed.

This ruleset prevents conflicts while respecting user intent — crucial for maintaining trust in collaborative editing.

Broadcasting Changes to Connected Clients

When a diagram saves, all connected users need immediate updates. I used SignalR groups, where each diagram creates a group identified by its ID:

private async Task DispatchAsync(Element diagramElement, string eventName, object data)
{
    await _hubContext.Clients
        .Group(diagramElement.Id.ToString())
        .SendAsync(eventName, data);
}
Enter fullscreen mode Exit fullscreen mode

This broadcasts to everyone viewing that diagram — both authenticated users and anonymous viewers using share links. The group abstraction makes this remarkably simple.

Applying Updates on the Frontend

When the frontend receives update events, it must merge incoming changes with the current state without disrupting the user’s work. The process:

  1. Deserialize the incoming diagram state
  2. Identify which shapes changed
  3. Reuse existing shape instances where possible (preserves UI state)
  4. Apply property updates using the same merge rules
  5. Trigger re-rendering only for affected elements

This selective update approach maintains smooth interaction even during active collaboration sessions.

Lessons Learned

Building real-time collaboration taught me several valuable lessons:

Start with the right abstractions

Choosing SignalR over raw WebSockets saved weeks of development time and provided battle-tested solutions for complex problems like reconnection and transport fallbacks.

Conflict resolution requires clear rules

Without explicit merge logic, concurrent edits quickly become chaotic. Define your rules early and test them thoroughly.

User experience matters more than technical elegance

The system needed to “just work” for users, even if that meant additional complexity in the implementation.

Conclusion

Real-time collaboration in Modeldraw now supports teams creating UML diagrams, flowcharts, and agile workflows together seamlessly. Users can see each other’s cursors, make simultaneous edits, and trust that their changes won’t be lost — all thanks to SignalR’s robust foundation and careful conflict resolution logic.

You can see it in action at modeldraw.com.

Top comments (0)