Collaboration
AFFiNE enables seamless real-time collaboration with team members, allowing multiple users to edit documents, whiteboards, and databases simultaneously. Built on Conflict-free Replicated Data Types (CRDTs) using Y.js (Yjs), AFFiNE ensures your edits are always preserved, even when working offline.Real-Time Editing
Collaborate with your team in real-time:- Live cursors: See where teammates are editing
- Instant updates: Changes appear immediately for all users
- Presence indicators: Know who’s viewing or editing
- Conflict-free: Multiple users can edit the same content simultaneously
- Undo/redo: Individual undo stacks per user
AFFiNE uses Socket.io over WebSockets for real-time communication, with automatic reconnection and offline support.
Architecture Overview
AFFiNE’s collaboration is powered by:Y.js (Yjs) CRDT
Conflict-free Replicated Data Type ensuring all edits merge without conflicts
Socket.io Gateway
WebSocket server managing real-time connections and message broadcasting
Document Storage
PostgreSQL backend persisting document updates and snapshots
Awareness Protocol
User presence tracking cursors, selections, and online status
How It Works
CRDT-Based Sync
AFFiNE uses Y.js, a high-performance CRDT implementation:- No locking: Users never block each other
- Automatic merging: Concurrent edits merge intelligently
- Offline support: Edits sync when connection returns
- No conflicts: Mathematical guarantees of consistency
WebSocket Protocol
Real-time sync uses Socket.io events:- Connection Events
- Document Sync
- Presence/Awareness
Client → Server:
space:join- Join workspace for syncspace:leave- Leave workspacespace:join-awareness- Join presence for specific docspace:leave-awareness- Leave presence
- Connection acknowledgment with
clientId - Success/failure status
Update Merging
The server optimizes network traffic:Technical Implementation (gateway.ts)
Technical Implementation (gateway.ts)
The
SpaceSyncGateway class manages all real-time collaboration:Key Components:@WebSocketGateway()- Socket.io integrationSpaceSyncAdapter- Protocol versioning (sync-025, sync-026)WorkspaceSyncAdapter- Workspace-specific logicUserspaceSyncAdapter- Personal space logic
- Tracks active users and connections
- Implements presence user ID resolution
- Flushes active user metrics every minute
- Handles connection/disconnection events
- Supports clients ≥ 0.25.0
- Protocol 0.25: Single update broadcasts
- Protocol 0.26: Batch update broadcasts (optimized)
- Automatic protocol selection based on client version
User Presence
See who’s actively working:Presence Indicators
- Avatars in top-right corner show active users
- Live cursors display teammate positions
- Colored highlights show text selections
- User count badge indicates total viewers
Awareness Features
In Documents
- Cursor positions as you type
- Block selections when highlighting
- User name labels near cursors
- Different colors per user
In Whiteboards
- Mouse/pointer positions
- Selected shapes and elements
- Active drawing tools
- Viewport indicators (who’s viewing where)
Permissions and Access
Workspace Roles
Control who can collaborate:- Owner: Full access and workspace management
- Admin: Manage members and permissions
- Member: Edit all workspace content
- Guest: View-only or limited edit access
Permissions are enforced by the
AccessController service before allowing WebSocket connections and document updates.Permission Checks
Document-Level Control
- Blocked documents: Prevent edits with
DocUpdateBlockederror - Read-only mode: View without edit permissions
- Private workspaces: Invite-only access
Offline Support
Work without internet, sync when back online:How Offline Works
- Local changes stored in browser IndexedDB
- Y.js tracks all unsent updates
- Connection restored → Updates sent to server
- Server merges offline changes with server state
- Conflicts resolved automatically via CRDT
Offline Indicators
- Red dot or warning when disconnected
- “Syncing…” message when reconnecting
- “Synced” checkmark when up to date
Conflict Resolution
How CRDTs Prevent Conflicts
Unlike traditional systems (last-write-wins), Y.js uses operation-based CRDTs: Example Scenario:- User A and User B both edit the same paragraph offline
- User A changes “Hello” → “Hello World”
- User B changes “Hello” → “Hi there”
- Both reconnect at the same time
CRDT Merge Strategies
CRDT Merge Strategies
Text Editing:
- Character-level operations tracked
- Position-based insertion (not index-based)
- Tombstones for deletions (preserved for sync)
- Item IDs for each element
- Concurrent insertions preserved
- Move operations supported
- Each block has unique ID
- Property changes merged per-field
- Deletion tombstones
- Row-level merging
- Cell updates merged independently
- Last-write-wins per cell (with timestamp)
Version History
Track document changes over time:- Automatic snapshots created periodically
- View history to see past versions
- Restore to previous state
- Compare versions side-by-side
- Editor attribution for each change
History Storage
- Fast document loading (from latest snapshot)
- Complete history preservation
- Efficient storage (updates compressed)
Performance Optimization
Server-Side
Update Compression
Multiple updates merged before broadcast to reduce bandwidth
Connection Pooling
Redis adapter for horizontal scaling across servers
Lazy Loading
Only sync document when user joins, not all workspace docs
State Vectors
Efficient diff calculation for late joiners
Client-Side
- Debounced sends: Batch local edits before sending
- Binary protocol: Efficient Y.js binary format
- Incremental parsing: Apply updates without re-rendering entire doc
- Virtual scrolling: Handle large collaborative documents
Collaborative Features by Module
Editor Collaboration
- Paragraph-level: Multiple users edit different paragraphs
- Inline formatting: Concurrent bold, italic, link edits
- Block operations: Insert, delete, move blocks
- Copy/paste: Preserve formatting and structure
Whiteboard Collaboration
- Element positioning: Drag shapes simultaneously
- Drawing: Concurrent pen strokes
- Connectors: Auto-update when shapes move
- Frames: Collaborative presentation editing
Database Collaboration
- Row-level: Edit different rows simultaneously
- Cell-level: Concurrent edits to different cells
- Schema changes: Add columns collaboratively
- View configs: Independent filters/sorts per user
Notifications
Stay informed of team activity:- @mentions: Get notified when mentioned
- Page comments: Thread discussions on documents
- Activity feed: See recent changes (coming soon)
- Email digests: Summary of workspace activity (coming soon)
Best Practices
Collaborative Editing Tips
Collaborative Editing Tips
- Communicate: Use comments or chat when editing together
- Use sections: Divide work by headings or frames
- Check presence: See who’s editing before making big changes
- Save often: Autosave is automatic, but good to verify sync status
- Resolve conflicts early: Review version history if something looks wrong
- Use permissions: Set appropriate roles for team members
Troubleshooting
Connection Issues
Red dot or “Offline” indicator:- Check internet connection
- Refresh page to reconnect
- Check firewall/proxy settings for WebSocket support
- Verify you have edit permissions
- Check sync status in bottom-right corner
- Try disconnecting and reconnecting to workspace
- Rare but can happen with offline conflicts
- Check version history
- Manually merge or restore to previous version
Performance Issues
Slow syncing:- Large documents may take time to load
- Check network speed
- Clear browser cache and reload
- Close unused workspace tabs
- Restart browser
- Check for browser extensions interfering
Security
Encryption
- HTTPS/WSS: All connections encrypted in transit
- Authentication: Session tokens required for all operations
- Authorization: Permission checks before document access
- Token refresh: Automatic session renewal
Data Privacy
- Workspace isolation: Users can’t access other workspaces
- Document-level ACLs: Fine-grained access control
- Audit logs: Track who accessed what (enterprise)
- GDPR compliance: Data export and deletion