Skip to content

CRDT performance optimizations for concurrent editing #52

Description

@jonesd

Context

The system supports 10-20 concurrent editors on the same work. These optimizations would improve network efficiency, reduce latency, and extend capacity to 50-100+ concurrent editors.

Current State

Optimizations (in priority order)

1. Server-side delta batching (Medium effort, High impact)

Problem: Each character typed generates a crdt_sync_update that is relayed individually to all other sessions. A 50-character paste = 50 messages per recipient.

Solution: Batch deltas on the server before relaying:

  • Accumulate deltas for 50-100ms per work
  • Merge consecutive operations (Retain(1)x10 to Retain(10))
  • Send one batched message per recipient per interval
  • Falls back to immediate relay for single-character edits (low overhead)

Impact: Reduces WebSocket message count by 5-10x during rapid typing. At 20 users, a paste sends 20 messages instead of 1000.

2. Sequence-based reconnect (Medium effort, High impact)

Problem: On reconnect, client receives full CRDT state even if it only missed a few updates.

Solution: Track update sequence numbers:

  • Each crdt_sync_update carries a monotonic sequence number per work
  • Client stores its last-applied sequence
  • On reconnect, client sends {work_id, last_seq}
  • Server sends only updates after last_seq
  • If last_seq is too old (>1000 updates behind), fall back to full state

Impact: Reconnection is instant instead of multi-second. Critical for flaky networks and mobile.

3. Periodic CRDT snapshots (Medium effort, Medium impact)

Problem: Replay-based catch-up is O(n) in number of missed updates.

Solution: Server periodically creates compressed snapshots:

  • Every 30s or every 100 edits per work
  • On reconnect, client gets latest snapshot + subsequent deltas
  • Snapshots are memory-efficient (compressed CRDT state)

Impact: Catch-up time is O(log n) instead of O(n). Matters for works with long edit histories.

4. Delta compression (Low effort, Medium impact)

Problem: Deltas can contain redundant operations, especially after merging.

Solution: Compress deltas before relaying:

  • Merge consecutive Retain operations
  • Merge consecutive Insert operations (same author, adjacent position)
  • Drop no-op operations (Retain(0), Delete(0))
  • Optionally gzip large deltas (>1KB)

Impact: 2-3x reduction in delta payload size. No protocol changes needed.

5. Lazy CRDT materialization (Low effort, Medium impact)

Problem: Every 5 seconds, ALL pending CRDT docs are materialized to work revisions.

Solution: Smarter scheduling:

  • Only materialize docs with pending changes AND modified since last materialization
  • Add max-pending-threshold: force-materialize if >500 pending changes
  • Already partially implemented via pending_work_ids()

6. Binary protocol for CRDT updates (Large effort, High impact at scale)

Problem: CRDT updates use JSON encoding, which is verbose.

Solution: Use postcard (binary) encoding for CRDT-specific messages:

  • Delta operations as fixed-width integers instead of JSON strings
  • Awareness updates as binary structs
  • Keep JSON for non-performance-critical ops

Impact: 3-5x smaller payloads at high concurrency.

7. Per-work write lock sharding (XL effort, High impact at scale)

Problem: All edits go through one RwLock. The write lock serializes all mutations.

Solution: Shard the write lock per-work. Edits to different works don't block each other.

Maps to issue #18 (RwLock or Sharded Concurrency).

Priority

# Optimization Effort Impact
1 Delta batching M High
2 Sequence reconnect M High
3 CRDT snapshots M Medium
4 Delta compression L Medium
5 Lazy materialization L Medium
6 Binary protocol XL High
7 Write lock sharding XL High

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions