go-crdt

Pure-Go collaborative editing โ€” a replicated text document (crdt) and the service that carries it between the people writing it (collab), with the same merge logic on the server and in the browser.

CGO_ENABLED=0 zero dependencies in the engine js/wasm โ€” one implementation, not two offline editing, then reconcile no server arbitration, no operational transform amd64 ยท arm64 ยท riscv64 ยท loong64 ยท ppc64le ยท s390x 100% coverage fuzzed decoders
Documentation GitHub

A conflict-free replicated data type settles concurrent edits by the operations themselves, so nothing has to be authoritative. That is the whole point: no server decides who won, no operation is transformed on the way through, a participant can keep typing with the network down, and the server can be restarted without a handover protocol. The alternative โ€” operational transform, as used by ShareDB and Google Docs โ€” needs all three.

Written in Go so the browser can run it too. The engine compiles to js/wasm, which means a browser tab and the server execute the same merge implementation rather than two that have to agree. A JavaScript client paired with a Go server cannot make that claim. Mounted on grpc-transports/websocket the service reaches a browser with no sidecar and full bidirectional streaming.

Repositories

crdt libengine

Doc, List, Map, Composite, structured documents, awareness

a real 259 778-edit history replays in 18.4 ms and matches, character for character

A replicated document: any number of replicas edit at once, offline, over an unreliable transport, and converge. Three merging structures โ€” a text, a list, a map โ€” under one name, one snapshot and one thing to authorise; and a layer of document types built on them that adds no merge rule of its own: blocks, formatting, spreadsheets, isometric diagrams, movable trees, counters, sets, handwriting, chunked files, undo, and changes put up for review. Characters are stored as runs โ€” a thousand typed in a row cost one header and their text โ€” and the document walks both ways, so editing stays local. Convergence is proven by exhaustive permutation, not sampling. Zero dependencies, CGO=0, 100% statement coverage, and the whole suite runs as WebAssembly under Node in CI.

CI coverage 100%

collab libtransport

Collab gRPC service, Server, Client

three replicas across two runtimes converge, in CI

Carries a document between the people editing it: a per-document hub that fans out operations, welcomes late joiners with a snapshot, and keeps presence. The server arbitrates nothing โ€” it applies what it is sent and passes it on โ€” so a participant may edit while disconnected and the server may be restarted without anyone losing work. Documents persist to memory or PostgreSQL, and who may open which is decided per session. 100% coverage; the acceptance test runs two WebAssembly participants against a native one over a real WebSocket.

CI coverage 100%

How convergence is proven

Randomised sessions with late, reordered and duplicated delivery are a start, not a proof โ€” they sample the space of orderings rather than covering it. So small concurrent histories are also replayed in every possible order, and replicas are compared on their encoded state rather than merely their text, because agreeing on the text is the weaker claim. Every decoder is fuzzed, and doing so found five states a snapshot could describe that no replica could ever reach. The end-to-end gate runs three replicas across two runtimes โ€” one native, two compiled to WebAssembly and executed by Node through a real WebSocket โ€” and requires all three to converge with no character lost. A skipped test is not a passing one, so CI fails that job when the toolchain is missing rather than quietly turning it green.