This document describes the real-time collaborative editing system that enables multiple users to simultaneously edit workflows within the Sim platform. The system uses a Socket.IO-based operation queue pattern with optimistic local updates, server-side broadcasting, and automatic conflict resolution.
For information about the underlying workflow state management, see Workflow Fundamentals. For details on state persistence to the database, see State Persistence. For the undo/redo system that integrates with collaborative editing, see Undo/Redo System.
The collaborative editing system follows a client-server architecture where all workflow modifications flow through a sequential operation queue before being broadcast to connected clients via WebSocket.
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L34-L127" min=34 max=127 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L84-L189" min=84 max=189 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/workflows/workflow/store.ts#L114-L152" min=114 max=152 file-path="apps/sim/stores/workflows/workflow/store.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/database/operations.ts#L216-L235" min=216 max=235 file-path="apps/sim/socket/database/operations.ts">Hii</FileRef>
The operation queue ensures sequential processing of workflow modifications and provides retry logic with exponential backoff for failed operations.
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L17-L28" min=17 max=28 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L218-L307" min=218 max=307 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>
The useOperationQueueStore manages a queue of pending operations with the following state:
| Property | Type | Purpose |
|---|---|---|
operations | QueuedOperation[] | Ordered list of pending operations with retry metadata <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L85-L85" min=85 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
isProcessing | boolean | Mutex flag preventing concurrent operation processing <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L86-L86" min=86 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
hasOperationError | boolean | Triggers offline mode when operation exhausts retries <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L87-L87" min=87 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
QueuedOperation Structure:
Operation Targets and Constants:
| Target | Operation Constants | File Reference |
|---|---|---|
| BLOCKS | BATCH_ADD_BLOCKS, BATCH_REMOVE_BLOCKS, BATCH_UPDATE_POSITIONS, BATCH_UPDATE_PARENT, BATCH_TOGGLE_ENABLED, BATCH_TOGGLE_HANDLES, BATCH_TOGGLE_LOCKED | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L12-L12" min=12 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
| BLOCK | UPDATE_NAME, UPDATE_ADVANCED_MODE, UPDATE_CANONICAL_MODE | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L11-L11" min=11 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
| EDGES | BATCH_ADD_EDGES, BATCH_REMOVE_EDGES | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L13-L13" min=13 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
| SUBBLOCK | UPDATE | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L15-L15" min=15 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
| VARIABLE | ADD, UPDATE, REMOVE | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L17-L17" min=17 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
| WORKFLOW | REPLACE_STATE | <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L18-L18" min=18 file-path="apps/sim/socket/constants.ts">Hii</FileRef> |
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L84-L130" min=84 max=130 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/constants.ts#L1-L22" min=1 max=22 file-path="apps/sim/socket/constants.ts">Hii</FileRef>
The addToQueue function implements intelligent deduplication to prevent redundant operations:
(blockId, subblockId) to ensure rapid typing only sends the final value <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L90-L109" min=90 max=109 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>.(variableId, field) <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L111-L130" min=111 max=130 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>.<FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L143-L152" min=143 max=152 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>.<FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L154-L155" min=154 max=155 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>.The system uses Socket.IO for bidirectional real-time communication between clients and the server.
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L161-L241" min=161 max=241 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L191-L216" min=191 max=216 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/socket/database/operations.ts#L216-L240" min=216 max=240 file-path="apps/sim/socket/database/operations.ts">Hii</FileRef>
| Event Name | Direction | Payload | Handler |
|---|---|---|---|
workflow-operation | Client ↔ Server | {operation, target, payload, userId, metadata: {workflowId}} | onWorkflowOperation <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L161-L161" min=161 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef> |
subblock-update | Client ↔ Server | {workflowId, blockId, subblockId, value, userId, operationId} | onSubblockUpdate <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L457-L457" min=457 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef> |
variable-update | Client ↔ Server | {workflowId, variableId, field, value, userId, operationId} | onVariableUpdate <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L488-L488" min=488 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef> |
operation-confirmed | Server → Client | {operationId} | onOperationConfirmed <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L191-L191" min=191 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
operation-failed | Server → Client | {operationId, error, retryable} | onOperationFailed <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L218-L218" min=218 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
The system distinguishes between local changes (initiated by the current user) and remote changes (broadcast from other users) to prevent infinite loops and maintain consistency.
The isApplyingRemoteChange ref prevents infinite loops by tracking whether the current state update originated from a remote broadcast:
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L140-L140" min=140 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L161-L180" min=161 max=180 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>
The system uses workflowId filtering and optimistic updates to minimize conflicts.
Each workflow operates in an isolated Socket.IO room. Broadcasts are filtered by activeWorkflowId to prevent cross-tab interference <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L167-L172" min=167 max=172 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>.
When viewing a baseline diff (comparing current state to a snapshot), collaborative operations are blocked to prevent accidental modifications to the draft state <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L137-L138" min=137 max=138 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>, <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L656-L660" min=656 max=660 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>.
The system displays real-time cursor positions of all collaborators on the workflow canvas.
screenToFlowPosition [apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:250]().Cursors component receives updates and renders SVG overlays positioned relative to the shared flow coordinates [apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/cursors/cursors.tsx]().The system implements sophisticated error handling with different strategies for value operations vs structural operations.
| Operation Type | Timeout Constant | Value | Max Retries |
|---|---|---|---|
| Subblock/Variable Updates | SUBBLOCK_VARIABLE_TIMEOUT_MS | 15000ms | 5 <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L18-L22" min=18 max=22 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
| Structural Operations | STRUCTURAL_TIMEOUT_MS | 5000ms | 3 <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L20-L24" min=20 max=24 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef> |
When an operation exhausts retry attempts or fails with a non-retryable error, the system enters a failure state to prevent further state divergence by setting hasOperationError: true and clearing pending operations <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/stores/operation-queue/store.ts#L501-L512" min=501 max=512 file-path="apps/sim/stores/operation-queue/store.ts">Hii</FileRef>.
The system handles special events when workflows are deleted or reverted by other users.
When a workflow is reverted to its deployed state, all connected clients reload the workflow state from the server to ensure consistency <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L537-L550" min=537 max=550 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>.
Sources: <FileRef file-url="https://github.com/simstudioai/sim/blob/7d0fdefb/apps/sim/hooks/use-collaborative-workflow.ts#L537-L614" min=537 max=614 file-path="apps/sim/hooks/use-collaborative-workflow.ts">Hii</FileRef>
Refresh this wiki