CRDT & Collaboration
Relevant source files
The following files were used as context for generating this wiki page:
The CRDT (Conflict-free Replicated Data Type) system provides an abstraction layer for real-time collaborative editing within n8n. It enables multiple users to synchronize document states, such as workflows, across different peers and transports. The system is built on the Yjs engine to ensure eventual consistency and handles synchronization through various transport mechanisms including WebSockets and MessagePorts.
Sources: packages/@n8n/crdt/README.md:1-5
Architecture and Core Components
The CRDT module is organized around a provider-based architecture that separates document management from data transmission.
Component Hierarchy
- CRDTProvider: A factory class that creates and manages CRDT documents.
- CRDTDoc: A document container that holds specific data structures like maps and arrays.
- SyncProvider: Orchestrates the synchronization logic between a
CRDTDocand aSyncTransport. - SyncTransport: An interface defining how binary synchronization data moves between peers.
Sources: packages/@n8n/crdt/README.md:46-60
The following diagram illustrates the relationship between these core components during a collaborative session:
Sources: packages/@n8n/crdt/README.md:46-70
Data Structures
The system supports two primary collaborative data structures: CRDTMap and CRDTArray.
CRDTMap
This structure stores key-value pairs and supports deep change observation. It provides a onDeepChange method that triggers when properties are modified, even within nested structures.
- Conflict Resolution: Concurrent edits to the same key use a "last-write-wins" strategy.
- Atomic Values: Plain objects stored in a map are treated as atomic values. To achieve fine-grained merging, you must use nested CRDT maps.
Sources: packages/@n8n/crdt/README.md:12-40
CRDTArray
This represents an ordered list. Changes to arrays are emitted in the Quill delta format, including retain, insert, and delete operations.
Sources: packages/@n8n/crdt/README.md:46-55
Synchronization and Transports
The synchronization process involves moving binary Uint8Array data between peers using a transport layer.
| Transport Type | Use Case |
|---|---|
| WebSocketTransport | Server-side synchronization with features like auto-reconnect and configurable delays. |
| MessagePortTransport | Communication between the main thread and Web Workers or SharedWorkers. |
| MockTransport | In-memory synchronization primarily used for unit testing and local simulations. |
Sources: packages/@n8n/crdt/README.md:60-95
The following sequence diagram shows the initialization and data flow between two peers:
Integration with Workflow Builder
The CRDT system is a foundational element for features like the AI Workflow Builder. This builder operates by generating JavaScript code representing a graph of nodes. While the CRDT handles the underlying data consistency, the higher-level services use these structures to maintain a shared state of the workflow being built.
- Node Management: Individual nodes are often represented as entries in a
CRDTMap. - Code Generation: Services like
buildCodeBuilderPromptutilize the current workflow state (which may be synchronized via CRDT) to provide context for AI agents.
Sources: packages/@n8n/ai-workflow-builder.ee/src/code-builder/prompts/index.ts:40-60, packages/@n8n/crdt/README.md:15-20
Usage Implementation
To implement collaborative editing, you initialize a provider with a specific engine (currently Yjs) and link a sync provider to a transport.
import { createCRDTProvider, createSyncProvider, WebSocketTransport, CRDTEngine } from '@n8n/crdt';
// 1. Initialize Provider
const provider = createCRDTProvider({ engine: CRDTEngine.yjs });
const doc = provider.createDoc('workflow-id');
// 2. Setup Transport
const transport = new WebSocketTransport({ url: 'wss://n8n-instance/sync' });
// 3. Link and Start Sync
const sync = createSyncProvider(doc, transport);
await sync.start();
// 4. Manipulate Data
const nodes = doc.getMap('nodes');
nodes.set('node-uuid', { type: 'httpRequest', position: [100, 100] });
Sources: packages/@n8n/crdt/README.md:7-15, packages/@n8n/crdt/README.md:73-85
Conflict Prevention Guidelines
When working with the CRDT layer, you should follow these rules to avoid unexpected data loss:
- Replace Whole Objects: To update a property inside a plain JavaScript object stored in a map, you must replace the entire object.
- Granular Maps: Use separate
CRDTMapinstances for values that require concurrent merging (e.g., individual node coordinates). - Transactions: Wrap multiple related changes in a
transact()call to ensure they are propagated as a single atomic update.
Sources: packages/@n8n/crdt/README.md:25-45
Summary
The CRDT & Collaboration system enables high-performance, conflict-free document synchronization in n8n. By abstracting Yjs through a unified API and supporting multiple transport protocols, it allows the frontend and backend to maintain a consistent view of workflows during multi-user sessions. This infrastructure supports advanced features such as the collaborative AI Workflow Builder and real-time canvas updates.
Sources: packages/@n8n/crdt/README.md:1-5, packages/cli/src/collaboration/collaboration.service.ts