DocsConceptsOpLog and DocState Separation

OpLog and DocState

Quick Reference

  • OpLog = Sequence of events/operations that compose the document history
  • DocState = Current materialized state of the document

This separation enables time travel, efficient sync, and flexible storage strategies.

Key Concepts

OpLog (Operation Log)

  • Append-only sequence of operations
  • Causal relationships and metadata

DocState (Document State)

  • Current materialized view of the document
  • Actual data structures and values
  • What your app reads and displays

Benefits

  • Memory efficiency: Load OpLog without state (relay servers)
  • Time travel: Navigate history without losing the log
  • Fast startup: Load state via snapshots, fetch history later
  • Flexible storage: Store separately for optimization
const  = new ();
 
// Edit updates both
.("text").(0, "Hello");
.(.());  // Latest known version
.(.());       // The version of the current state of the document
// If the document is attached, they are the same.

Time Travel & Detachment

const  = new ();
.("text").(0, "v1");
const  = .();
 
.("text").(2, " -> v2");
 
// Checkout old version - DocState diverges from OpLog
.();
.(.());       // v1 state
.(.());  // Still has v2
.(.());    // true
 
// Return to latest
.();

Detached state: DocState shows old version while OpLog has all operations. Editing disabled by default.

Export Strategies

// Update: OpLog only (sync)
const  = .({ : "update" });
 
// Snapshot: OpLog + DocState (persistence)
const  = .({ : "snapshot" });
 
// Shallow: Minimal OpLog + DocState (fast startup)
const  = .({ : "shallow-snapshot", : .() });

Common Patterns

Relay Server (OpLog Only)

class  {
  private : ;
  constructor() {
    this. = new ();
    this..(); // Never materialize state
  }
 
  (: ) {
    this..();
  }
}

Best Practices

  • Export modes: Updates for sync, snapshots for persistence, shallow for startup
  • Optimize by use case:
    • Editors: Both in memory
    • Relays: OpLog only