Rebasely Beta: data may be purged

examples/live-notes Public

Markdown · 1.5 KiB · at 70b1506

id: 0001-single-sequencer-per-note
type: decision
owner: justin
reviewed: 2026-10-13
status: accepted

0001 One sequencer per note

Context

Two people editing the same note will type at the same moment. Something has to decide how their edits combine, and every editor has to reach the same text.

The options we looked at:

  1. A CRDT in every browser, with the server only relaying and storing.
  2. Peer-to-peer operational transform, where every client can order ops.
  3. Operational transform with one sequencer that orders all ops for a note.

Decision

Each note's Durable Object is the only place its edits are ordered. Editors send ops written against a version; the room transforms them past what they missed, applies them and broadcasts the result. Editors keep one op in flight and never order ops themselves.

Consequences

  • The transform only has to make pairs of ops converge. It never has to handle three-way puzzles between clients, so it fits in one small file ([[conflict-strategy]]).
  • A Durable Object already gives us one instance per name with single-threaded handling, so the sequencer costs nothing extra to build.
  • Every edit round-trips through the room before the next one is sent. Queued keystrokes are composed into one op, which keeps this unnoticeable at normal latencies.
  • No offline editing: an editor that loses the connection stops accepting input until it is back. A CRDT would allow it, at the cost of shipping one to the browser and storing its metadata with every note.