Crdt basics
Skill almasumdev/awesome-mobile-backend-agent-skills/.github/skills/sync/crdt-basics
When CRDTs help mobile apps, which libraries to use, and what to watch out for. Use when evaluating CRDTs for collaborative or offline-first features.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-backend-agent-skills --skill crdt-basicsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.4 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
CRDT Basics for Mobile
Instructions
CRDTs (Conflict-free Replicated Data Types) let multiple replicas of data converge without coordination. They are powerful -- and often overkill. Know when to use them.
1. When CRDTs Help
Use CRDTs when all of these hold:
- Clients edit shared state offline or concurrently.
- Automatic, lossless merge is required (not just "good enough" LWW).
- The data shape fits an available CRDT (counter, set, map, ordered list, text).
- You can accept the storage overhead (CRDT metadata often 2–10x the raw data size).
Good fits:
- Collaborative text editing (notes, docs).
- Shared lists (to-do, shopping).
- Presence / cursor positions.
- Counters without exact-once semantics (reaction counts, views).
Poor fits:
- Money, inventory, reservations. Anything requiring a global invariant or strong consistency.
- Simple single-writer data with an authoritative server. Plain optimistic concurrency is cheaper.
2. Flavors
- State-based (CvRDT): replicas send full state; merge is a join. Simple but costly for large state.
- Operation-based (CmRDT): replicas send operations; requires reliable, exactly-once broadcast.
- Delta-state: middle ground; send small deltas that apply via join.
Most modern mobile libraries (Yjs, Automerge 2) are delta-state under the hood.
3. Libraries
- Yjs (JS/TS, with ports to Rust and iOS/Android bridges) -- mature, fast, excellent for text and structured docs.
- Automerge 2 (Rust core, JS/Swift/Kotlin bindings) -- strong API, slower writes than Yjs for large documents but simpler mental model.
- y-crdt (Rust port of Yjs) -- good for native mobile.
- Loro (Rust) -- newer, competitive performance.
- Build-your-own for simple types (G-Counter, OR-Set) when you do not need full documents.
Pick based on language bindings available on your mobile platform and the document shape.
4. Server Role
Even with CRDTs, a server is usually present to:
- Relay operations between replicas (the "sync server").
- Persist snapshots for new clients joining later.
- Authorize access, throttle bad actors, and enforce rate limits.
The server can be "dumb" (a pub/sub relay) or "smart" (validates ops, applies domain rules). For multi-tenant systems, "smart" is almost mandatory.
// Node/TS: Yjs server relay (pseudo)
const docs = new Map<string, Y.Doc>();
ws.on("connection", (conn, { docId, userId }) => {
const doc = docs.get(docId) ?? load(docId);
const awareness = new Awareness(doc);
syncProtocol.readSyncMessage(conn, doc); // initial handshake
conn.on("message", buf => {
// validate user can write
Y.applyUpdate(doc, buf);
broadcast(docId, buf, conn); // fanout to peers
scheduleSnapshotSave(docId);
});
});
5. Storage
- Snapshot: a compacted state of the document.
- Updates: a log of encoded ops since the snapshot.
- Periodically compact: apply updates into a new snapshot, truncate the log.
Plan for 2–10x storage overhead vs plain JSON. Old peer metadata (tombstones) grows indefinitely unless you garbage-collect carefully.
6. Pitfalls
- Causality bugs: delivering an op before its dependencies causes subtle divergence. Use the library's transport; do not roll your own.
- Tombstone growth: every deleted element leaves a tombstone. Long-lived documents need periodic GC, which requires coordination.
- Identity: CRDTs identify elements by a
(replica_id, counter)pair. Ifreplica_idrepeats (e.g., client reuses an id across reinstalls), divergence follows. Generate a freshreplica_idon first app launch and persist it. - Large documents on slow devices: merging a 10 MB Yjs doc on a low-end Android can be slow. Shard documents (per chapter, per board).
- Binary format stability: the CRDT's binary encoding must not change between app versions without a migration plan.
7. Auth and Multi-Tenancy
- Sign every op with the user id; the server validates before relaying.
- Per-document ACLs; do not trust the client to enforce them.
- Rate-limit ops per user per document.
- For billed tenants, account for CRDT storage in the pricing model -- tombstones and history are real costs.
8. Mobile Integration Sketch
iOS (Swift + y-crdt via C bindings):
let doc = YDoc()
let text = doc.getText("body")
doc.observe { update in
syncChannel.send(update)
}
syncChannel.onUpdate { update in
doc.applyUpdate(update)
}
Android (Kotlin + y-crdt JNI):
val doc = YDoc()
val text = doc.getText("body")
doc.onUpdate { update -> syncChannel.send(update) }
syncChannel.setListener { update -> doc.applyUpdate(update) }
9. Degrade Gracefully
If the CRDT approach does not fit one endpoint, do not force it. Most apps use CRDTs for specific collaborative screens and plain REST + optimistic concurrency for the rest.
Checklist
- Use case verified (offline concurrent edits + lossless merge needed).
- Library chosen with bindings on both mobile platforms.
- Server role defined (relay vs authoritative).
-
replica_idgenerated once per install and persisted. - Snapshot + update log storage with periodic compaction.
- Tombstone GC strategy documented.
- Binary format versioning / migration plan in place.
- Authz and rate limiting applied at the relay.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.