GenosDB vs Yjs and Automerge: Real-Time Collaboration Without a CRDT Library
How Yjs and Automerge solve collaborative editing, what each one costs you in infrastructure — and how GenosDB reaches the same live experience with a database that already ships identity, permissions and P2P transport.

Full Stack Developer - dWEB R&D
The Problem Everyone Solves the Same Way
Two people open the same document. Both type. Nobody loses a word.
The standard answer to that requirement is a CRDT library — usually Yjs or Automerge. Both are excellent, and both solve the hardest part of the problem: merging concurrent edits without a coordinator. But a CRDT library is a merge engine, not an application backend. Once it is in place, the rest of the system is still missing — and most of what is missing is what your app actually spends its code on.
This article looks at what each library does, what it leaves for you to build, and how the same live experience can be reached with a database that already carries the missing pieces.
What Yjs Actually Does
Yjs is a shared-types library built on YATA, a sequence CRDT. Its data structures — Y.Text, Y.Array, Y.Map — merge concurrent operations deterministically, so every peer converges on the same document regardless of arrival order.
Its strengths are real and worth naming:
- Character-level merge. Two cursors inside the same sentence interleave correctly. This is the hard case, and Yjs handles it.
- State vectors. A peer describes what it has as
{clientID → clock}, and the other side computes an exact delta. Efficient when writers are few and stable. - Mature editor bindings. ProseMirror, CodeMirror, Monaco, Quill, TipTap — the integration work is done and battle-tested.
- Pure JavaScript, with tombstone garbage collection and
Y.mergeUpdatesfor compacting history without instantiating a document. A Rust port (yrs) exists for native peers.
What Yjs is not, by design, is a stack. It is a merge engine, and everything around it is a separate decision:
- Transport. The public demos run against a y-websocket server. There are WebRTC providers, but the well-trodden path — the one every tutorial takes — is a server relaying updates.
- Persistence.
y-indexeddbis a separate package, wired by you. - Identity, permissions, queries. Not in scope. A Yjs document has no concept of who wrote what, no roles, and nothing to query — it is a document, not a database.
One detail is worth pulling out, because it shapes everything below: awareness — the cursors, selections, names and colours you see moving on screen — is not CRDT data even in Yjs. It travels on a separate, ephemeral protocol and dies with the session. Yjs made that call deliberately: presence is not history, so it should not pay the price of history.
What Automerge Actually Does
Automerge takes a different route: an operation-based CRDT with full history. Every change is a node in a hash-addressed DAG — the same idea as a Git commit graph — so a document carries its own past, and time travel and per-character attribution come for free.
Its strengths:
- Character-level merge, like Yjs, plus rich text with marks.
- History as a first-class citizen. Every version is reachable and every change is attributable, without you designing a versioning scheme.
- Efficient sync protocol. Peers exchange heads plus Bloom filters; identical heads mean nothing is transferred.
- Cross-platform core in Rust, compiled to WASM for the browser.
And its costs, which are the flip side of the same design:
- A document never forgets. History is the data model, so opening a long-lived document means loading its past, and the cost grows with the document's lifetime rather than with its current size.
- WASM in the bundle. Fine for most apps, awkward for some environments and for cold-start budgets.
- Access control is a separate layer. Keyhive is the answer being built for it, and it is explicitly experimental.
- A sync server in the standard setup.
automerge-repoships one, and the documented path uses it.
The Dividing Line, Stated Plainly
There is exactly one thing these libraries do that a plain database cannot: merge two edits inside the same sentence, at the same instant, character by character. If two people are typing into the same line of the same paragraph simultaneously, a sequence CRDT interleaves their keystrokes and nothing is lost.
That capability is genuinely hard to build, and it is the reason both projects exist. It is also, in the collaborative applications most teams actually ship, the rarest case in the room — and the one that human beings avoid on their own the moment they can see where everyone else is standing. That is the observation Notion, Linear and every block editor since have been built on: make presence visible and collisions mostly stop happening.
Everything else people reach for a CRDT to get — concurrent edits across a document, ordering that survives simultaneous inserts, offline writes that reconcile on reconnect, live cursors — does not require a sequence CRDT at all. It requires the right granularity and a presence channel.
The Other Path: One Node per Paragraph
GenosDB is a peer-to-peer graph database, not an editor library. But because a document can be modelled as data, collaborative editing falls out of the database's own primitives. The live example is a continuous document — write, press Enter, keep writing — implemented in one HTML file with no editor framework and no CRDT dependency. The technique has four parts:
- A paragraph is a node. Editing a paragraph rewrites only that node, so two people working on different paragraphs never overwrite each other — there is no shared node to fight over. Last-write-wins is a problem only when two writers share a node, and at paragraph granularity they usually do not.
- Fractional order keys. A paragraph inserted between order
1and2gets a key in the gap. Two peers inserting into the same gap concurrently mint different keys, so both survive, and every peer sorts them identically. No counters to coordinate, no rebalancing to synchronise. - Structure is graph operations. Enter splits a paragraph into two nodes; Backspace at the start merges a paragraph into the previous one and deletes it; pasting multi-line text creates one node per line. Concurrent structural edits land on different nodes, so they compose instead of conflicting.
- Awareness on an ephemeral channel. Named, coloured carets and live selections travel over a GenosRTC data channel and never touch the graph — the same architectural decision Yjs made, reached from the same reasoning. And the paragraph being typed is broadcast keystroke by keystroke, so remote windows move character by character, while the debounced database write remains the truth that persists and repairs.
The result behaves like the CRDT demos: type in one window, watch it appear letter by letter in the other, with a named cursor showing where your collaborator is.

Every window is a separate peer. The coloured cursors and selections travel on the ephemeral channel; the text itself lives in the graph.
Why the Path Is Shorter
Both approaches produce live text on a remote screen. The difference is what a single keystroke has to do to get there.
In the standard CRDT setup, a keystroke is encoded into one or more CRDT operations, sent to a sync server, relayed to each peer, integrated into the receiving replica's structure, and rendered back through an editor binding. Every step is fast; there are simply several of them, and one of them is a round trip through infrastructure you have to run.
In the block-editor example, a keystroke is one hop over a direct WebRTC data channel — coalesced to at most one message per animation frame — and the receiver assigns a string to a native textarea. No encoding step, no integration step, no binding, no server. The graph write that persists it happens behind the live view, debounced, and repairs anything the network dropped.
That is an architectural difference, not a benchmark: fewer stages and no relay hop. It is also why the demo is a single file you can save and open, with nothing to deploy.
What Comes in the Same Package
This is where the comparison stops being about merge algorithms. A CRDT library gives you a document. GenosDB gives you a database that happens to be able to hold one — so the surrounding application does not need a second stack:
- Queries.
db.map({ query, field, order, \(limit })— filters, ordering, pagination, full-text matching and recursive graph traversal with\)edge. A document is a query result, not a special case. - Identity. Cryptographic, sovereign identities with mnemonic recovery and WebAuthn passkeys built in. Every operation can be signed by its author.
- Permissions. Role-based access control and node-level ACLs, enforced independently by every peer against the verified signer — a zero-trust model, not a client-side courtesy.
- Encryption. Field-level and record-level, with cryptographic read revocation.
- Persistence. OPFS-backed, offline by default. No adapter to choose.
- Transport. WebRTC peer-to-peer with automatic peer discovery and a Cellular Mesh overlay that keeps connection counts flat as rooms grow, instead of the O(n²) full mesh. No sync server anywhere in the picture.
None of that is bolted on for the editor: it is the same engine every other GenosDB application uses. The editor is roughly two hundred lines on top of it.
Offline Is Not a Feature You Add
The claim worth testing in a peer-to-peer system is not what happens while everyone is connected — it is what happens when they are not.
Run the example across multiple devices, disconnect the network entirely, write a different paragraph on each one, and reconnect. Every document converges, no matter how many peers wrote offline or in which order — because the graph is stored locally, the operation log carries what each peer missed, and a state digest lets converged peers exchange nothing at all. The live cursors come back on their own.
That behaviour is not editor code. It is the database doing what it does for every application built on it.
Choosing Between Them
Honest guidance, because the choice depends on the document, not on the marketing:
- Choose Yjs when multiple people genuinely type into the same sentence at the same time, when you need a mature binding for ProseMirror, Monaco or CodeMirror, or when you are adding collaboration to an editor you already ship.
- Choose Automerge when full, inspectable history is a product requirement — attribution, time travel, auditable versions — and you accept the cost of a document that never forgets.
- Choose GenosDB when the document is part of an application: when you also need queries, identity, permissions, encryption, offline persistence and peer-to-peer transport, and you would rather not run a sync server, assemble four packages, or maintain two data models side by side.
They are not mutually exclusive, either. Because GenosDB stores arbitrary values, binary CRDT updates can travel as ordinary nodes in the graph — the transport, persistence, identity and access control come from the database, and the merge engine stays whatever you chose. The point is not that CRDTs are unnecessary. It is that most collaborative applications reach for one to get things a database should already give them.
Try It
The example is a single HTML file, with no build step and nothing to deploy:
- 👉 Open the Block Editor — then open it again in a second window and type in both.
- 📄 Read the source — the technique is documented in comments, in place.
- 🧭 See how GenosDB compares across other P2P and distributed databases, or read the full GunDB guide if that is where you are coming from.
⭐ Found this useful? Star GenosDB on GitHub — or spin it up in seconds: npm i genosdb.
This article is part of the official documentation of GenosDB (GDB). GenosDB is a distributed, modular, peer-to-peer graph database built with a Zero-Trust Security Model, created by Esteban Fuster Pozzi (estebanrfp).
📄 Whitepaper | overview of GenosDB design and architecture
🛠 Roadmap | planned features and future updates
💡 Examples | code snippets and usage demos
📖 Documentation | full reference guide
🔍 API Reference | detailed API methods
💬 GitHub Discussions | community questions and feedback
🗂 Repository | Minified production-ready files
📦 Install via npm | quick setup instructions




