Overview
The sync system has three parts:- Schema (
packages/core/src/synchronizers/) - Defines input/output types - Client handler (
packages/client/src/handlers/) - Receives and processes sync data - Server synchronizer (
apps/server/src/synchronizers/) - Fetches and broadcasts data
Architecture
Sync flow:nodes.updates- Node attribute changesdocument.updates- Rich text document changescollaborations- Node collaborator updatesnode-reactions- Reactions on nodesnode-interactions- User interactionsnode-tombstones- Soft deletesusers- Workspace user updates
Step-by-step guide
Define the synchronizer schema
Create a schema file in Export from
packages/core/src/synchronizers/ with input and output types.packages/core/src/synchronizers/task-assignments.ts
packages/core/src/synchronizers/index.ts:Create the server synchronizer
Implement a synchronizer in
apps/server/src/synchronizers/ that extends BaseSynchronizer.apps/server/src/synchronizers/task-assignments.ts
Register the synchronizer
Add your synchronizer to the sync engine in
apps/server/src/services/sync-engine.ts:Create client handler (if needed)
If your sync data requires special client-side processing, create a handler in
packages/client/src/handlers/.For most cases, the default sync engine handles insertion automatically. Custom handlers are only needed for complex transformations or side effects.packages/client/src/handlers/synchronizers/task-assignments.ts
Synchronizer patterns
Basic data synchronization
Most synchronizers follow this pattern:- Fetch unsynced data where
revision > cursor - Transform database records to sync data format
- Return items with cursors for pagination
Event-based triggering
TheshouldFetch method determines which events trigger sync updates:
Pagination and cursors
The sync system uses revision-based cursors for efficient pagination:Database schema requirements
Tables used in synchronizers must have:- revision column (BIGINT or BIGSERIAL) - Auto-incrementing sync cursor
- Appropriate indexes on
revisionand filter columns - Timestamp columns (created_at, updated_at, deleted_at)
Event system integration
Emit events to trigger sync updates:apps/server/src/services/tasks.ts
Testing sync handlers
Performance considerations
- Limit batch size: Keep
limit(20)or similar to avoid overwhelming clients - Index properly: Add indexes on
revisionand filter columns - Avoid N+1 queries: Fetch related data in single queries when possible
- Use connection pooling: PostgreSQL connection pool handles concurrent sync requests
File locations
- Schemas:
packages/core/src/synchronizers/[name].ts - Server synchronizers:
apps/server/src/synchronizers/[name].ts - Client handlers:
packages/client/src/handlers/synchronizers/[name].ts - Sync engine:
apps/server/src/services/sync-engine.ts - Event bus:
apps/server/src/lib/event-bus.ts