System Design blueprint · Productivity software
Collaborative document editing (Google Docs)
Lets many users edit one document at the same time, online or offline, with live cursors, comments, permissions and full version history. It must never lose an acknowledged edit, and every replica must converge to the same document.
- Steps
- 9
- Subjective questions
- 33
- Objective questions
- 33
The problem and the outcome
Problem: Teams that email files or lock documents get conflicting copies, lost changes and no record of who changed what. Naive last-write-wins sync overwrites concurrent edits.
Outcome: Edits appear on collaborators' screens within moments, conflicts merge automatically without user intervention, and any past state can be inspected or restored. Offline work merges cleanly when the device reconnects.
Architecture
How it works, step by step
- The client opens a WebSocket to the gateway, which authenticates the user and asks the ACL service for their role (owner, editor, commenter, viewer) on that document; viewers get a read-only session.
- The gateway routes the connection to the single session server that owns the document (via consistent hashing or a lease). That server loads the latest snapshot plus the operation-log tail and sends the client the document at revision N.
- When the user types, the client applies the change locally at once and sends an operation tagged with its base revision (OT) or with unique element IDs and a vector clock (CRDT).
- The session server transforms the op against any concurrent ops since its base revision (OT) or merges it (CRDT), assigns the next revision, and durably appends it to the operation log before acknowledging the sender.
- The accepted op is published on the document's fan-out channel so every gateway holding a connection for that document pushes it to its clients, which transform or merge it into their local state.
- Cursor positions, selections and who-is-here are sent as throttled, ephemeral presence messages with a short TTL; they are broadcast but never written to the operation log.
- If the connection drops, the client keeps editing and stores ops in IndexedDB. On reconnect it fetches missed ops since its last acknowledged revision and replays its queue, which is rebased (OT) or merged (CRDT) without user action.
- Comments are stored separately and anchored to stable positions (CRDT element IDs or ranges transformed alongside edits), so they move with text; the comment and suggest permissions are enforced server-side on every op.
- A background compactor writes a snapshot every N ops so loads stay fast; version history serves any revision by loading the nearest earlier snapshot and replaying ops, and a change feed drives notifications and search indexing.
Tech stack
- WebSockets with HTTP long-poll fallback
- Yjs or Automerge (CRDT) or ShareDB (OT)
- Redis pub/sub or NATS for per-document fan-out
- PostgreSQL or a distributed SQL store for the operation log
- S3-compatible object storage for snapshots
- IndexedDB for client-side offline queue
- Kafka for change events to notifications and search
- Zookeeper/etcd or consistent hashing for document ownership leases
Key design decisions
- OT with a central sequencer versus CRDT: OT keeps documents compact and is proven in server-centred editors like Google Docs; CRDTs make offline and peer-to-peer merging simpler at the cost of metadata growth and tombstones.
- One session server owns each document so ordering and transformation happen in one place; ownership is a lease that moves on failure, and the op log is the source of truth for recovery.
- Acknowledge an edit only after it is durably appended to the operation log, so a server crash never loses an edit the user believes was saved.
- Presence is kept out of the durable path: in-memory with TTL, throttled to a few updates per second per user, and allowed to be lossy.
- Snapshots plus op log rather than storing only full versions: cheap per-keystroke writes, fast loads from snapshots, and exact replay for history and audit.
Common mistakes
- Using last-write-wins on whole documents or paragraphs, which silently discards a collaborator's concurrent edits.
- Letting two servers accept ops for the same document during a failover split-brain; fence with lease epochs so stale owners are rejected by the op log.
- Never compacting CRDT tombstones or the op log, so large old documents load slowly and consume growing memory.
- Checking permissions only when the socket opens; a revoked editor keeps writing unless every op is re-validated or sessions are terminated on ACL change.
- Anchoring comments to raw character offsets, which drift or point to deleted text after concurrent edits.
What to measure
- Edit propagation latency (p50/p99) from sender keystroke to peer render
- Op acknowledgement latency and op log append error rate
- Document open time, split by snapshot load and op-tail replay
- Reconnect merge success rate and size of offline queues replayed
- Divergence detections (replica checksum mismatches) per million ops
Most-asked interview questions
Subjective questions 33
1Would you choose operational transformation or CRDTs for this system, and why?Asked almost every time
It depends on the editing model. If every edit goes through a server, OT with a central sequencer is a proven choice: the server orders ops, transforms concurrent ones against each other, and the document stays compact. Google Docs works this way. If offline editing, multi-device sync or peer-to-peer matter a lot, I lean towards a CRDT such as Yjs or Automerge, because any replica can merge any set of ops in any order and still converge, with no central transform step. The cost is metadata: element IDs and tombstones grow, so I need compaction and snapshotting. In either case I still keep a server-side op log, because history, audit, permissions and recovery need one authoritative record.
2How do you handle a user who edits offline for hours and then reconnects?Asked almost every time
While offline, the client applies edits locally and persists them in IndexedDB, along with the last revision the server acknowledged. On reconnect it first fetches all ops the server accepted after that revision. With OT, the client transforms its pending queue against those ops and sends them rebased on the current revision; with a CRDT, it simply exchanges missing updates using state vectors and both sides merge. The server treats replayed ops like any other: it checks the user still has edit permission, assigns revisions and appends them durably. Ops carry client IDs and sequence numbers so retries are idempotent. For very long offline sessions I may show the user a summary of what changed, but the merge itself is automatic.
3Walk me through what happens end to end when a user types a single character.Asked almost every time
The client applies the character to its local model immediately, so typing feels instant. It wraps the change in an operation with its base revision (OT) or a unique element ID (CRDT) and sends it over the existing WebSocket. The gateway forwards it to the session server that owns the document. That server checks the user's permission, transforms or merges the op against anything newer than its base, assigns the next revision, and appends it durably to the operation log. Only then does it acknowledge the sender. It publishes the op on the document's fan-out channel. Every gateway with clients on that document pushes it out, and each client transforms or merges it into local state. Presence updates travel separately and are never logged.
4How do you guarantee that an acknowledged edit is never lost?Asked almost every time
The rule is simple: no acknowledgement until the op is durable. The session server appends the op to a replicated, append-only log and waits for a quorum or synchronous replica to confirm before sending the ack. If the server crashes after the write but before the ack, the client retries with the same client ID and sequence number, and the server sees it is already logged and returns the existing revision. If it crashes before the write, the client still holds the op as pending and resends it. Snapshots are only an optimisation built from the log, never the source of truth. Backups, and checksums on snapshots, guard against corruption and operator mistakes.
5What happens when the session server that owns a document crashes mid-session?Asked almost every time
Clients see the WebSocket drop and enter reconnect mode. They keep editing locally and queue unacknowledged ops. Ownership is held by a lease in a coordination service such as etcd or ZooKeeper. Once the lease expires, another server acquires it with a higher fencing token, loads the latest snapshot and replays the log tail to rebuild the exact state at the last durable revision. Clients reconnect through the gateway, which now routes to the new owner. Each client sends its last acknowledged revision, receives the missed ops, and resubmits pending ops with their original IDs so duplicates are ignored. Users usually notice only a brief 'reconnecting' indicator, and nothing acknowledged is lost because the log is the source of truth.
6How do you handle a user whose permission is revoked while they have the document open?Asked almost every time
Permission is checked on every op at the session server, not only when the WebSocket opens. The ACL service publishes change events. The session server and gateway subscribe to them, invalidate any cached role and re-evaluate open sessions for that document. If a user is downgraded to viewer, their next edit op is rejected and the client switches to read-only. If access is removed entirely, the server closes the session and stops fan-out to that client. Cached roles carry a short TTL as a safety net in case an event is missed. Ops from an offline client are checked against the current role on reconnect, so stale permissions cannot be used to write later.
7How do you make op submission safe under network retries?Asked almost every time
Each client session has a unique client ID and numbers its ops with a strictly increasing sequence. The pair (client_id, seq) is the idempotency key, and the log enforces it as unique per document. If an ack is lost and the client resends, the server finds the existing entry and returns the original revision instead of applying the op twice. The server also tracks the last applied seq per client. A gap shows that a message is missing, so the server asks for a resend rather than applying ops out of order. CRDTs are naturally tolerant of duplicates because element IDs are unique, but deduplicating at the log still saves storage and keeps the revision history clean.
8How do you scale WebSocket sessions when one document has hundreds of active editors?Very often asked
I separate connection handling from document logic. Many stateless gateways hold the sockets; one session server owns the document and does ordering. Accepted ops are published once to a per-document channel, and each gateway subscribed to that channel fans out to its local clients, so the session server does not write to hundreds of sockets. Presence is the noisier stream, so I throttle cursor updates, batch them, and for very large audiences show only a subset of cursors. Clients can also batch keystrokes into small op groups. If a document has far more viewers than editors, viewers can subscribe to the fan-out without touching the session server. Ownership leases with epochs make failover safe.
9How do you stop two session servers from both believing they own the same document?Very often asked
A lease alone is not enough, because a server paused by a long GC or a network partition may not know its lease has expired. Each lease grant comes with a monotonically increasing fencing token. The operation log store accepts appends only when the writer's token is at least the highest token it has seen for that document, and it rejects older ones. A stale owner's writes then fail, and that server must drop its sessions. A conditional append also helps: write revision N+1 only if the current head is N. Together these make the log the arbiter, so even a brief split brain cannot produce two different op sequences with the same revision numbers.
10Design the data model for the operation log, snapshots and documents.Very often asked
I would use a documents table holding doc_id, owner, title, created time, the current head revision and the latest snapshot revision. The operation log is keyed by (doc_id, revision). Each row stores the op payload, author user ID, client ID, client sequence number, timestamp and op format version. A unique constraint on (doc_id, client_id, client_seq) gives idempotency. Snapshots are keyed by (doc_id, revision), and the serialised document goes in object storage with a checksum. ACLs live in their own service as (doc_id, principal, role). Comments are stored separately as (comment_id, doc_id, anchor, thread, author, resolved state). Partitioning everything by doc_id keeps a document's data together, which suits the single-owner model.
11How would you do a back-of-envelope capacity estimate for this system?Very often asked
I would state my assumptions clearly and derive from them. Start with concurrently open documents and the average number of active editors per document. Then estimate ops per second per editor after client-side batching, since keystrokes are coalesced into small ops. Multiplying gives total op writes per second to the log, and multiplying again by average op size gives write bandwidth. Fan-out traffic is ops multiplied by recipients per document, so it grows with collaborators, not just writers. Presence traffic is often larger than edit traffic, which is why it is throttled. Storage is ops per day times op size, plus snapshots. Finally, concurrent WebSocket connections divided by safe connections per gateway node tells you how many gateways you need.
12How does version history work, and how do you keep it fast for old revisions?Very often asked
Every revision exists implicitly because the log is complete. To show revision R, load the nearest snapshot at or before R and replay ops up to R. Cost is bounded by the snapshot interval, so old revisions are as cheap to load as recent ones. For the history UI, users do not want every keystroke. I group ops into named or time-bucketed versions by author and session, and I store a lightweight diff summary so the list renders without replaying anything. Restoring an old version should not rewrite history. It appends new ops that move the document to that state, so the restore can itself be undone and no collaborator's work disappears.
13How would you implement undo in a collaborative editor?Very often asked
Undo must be local. Pressing Ctrl+Z should undo my last change, not a colleague's. The client keeps a stack of its own ops. To undo one, it computes the inverse op, such as a delete for an insert, and then transforms that inverse against every op applied since, including remote ones, so it lands in the right place in today's document. The result is sent as a normal new op, so history stays append-only and other clients just see another edit. With CRDTs, undoing a delete means reviving the tombstoned elements, and undoing an insert means deleting those IDs. Redo is the same idea in reverse. Edge cases, such as undoing text someone else has since deleted, need sensible no-op behaviour.
14CRDTs keep tombstones for deleted characters. How do you stop documents from growing forever?Very often asked
Tombstones exist because a concurrent insert might reference a deleted element as its neighbour. They can only be removed safely once every replica has seen the deletion, a state called causal stability. With a central server, that becomes practical. The server tracks the minimum acknowledged version across all known replicas and garbage-collects tombstones older than that during compaction. The catch is long-offline clients: you cannot wait forever. A common policy is a horizon after which a stale client cannot merge directly. It must rebase its pending ops onto a fresh snapshot. Modern sequence CRDTs such as Yjs also compress runs of consecutive elements into blocks, which keeps metadata small even before garbage collection.
15Users in India and the US edit the same document. Where does it live, and what do they experience?Very often asked
With a single-owner design, the document's session server lives in one region, ideally near most of its active editors, and ownership can move when usage shifts. Remote users pay a cross-region round trip for acknowledgements and for seeing others' edits. Their own typing stays instant because the client applies ops locally first, and they see colleagues' changes after the propagation delay. Gateways remain local to each user, so TLS and the WebSocket terminate nearby, while the op path rides the backbone to the owner. The log is replicated across regions for disaster recovery. Multi-master per document is possible with CRDTs, but it complicates ordering, permissions and revision numbers, so most production systems keep one owner.
16Why use a single owning session server per document instead of letting any server accept edits?Very often asked
A single owner gives a total order of ops for free. It assigns revision N+1, keeps the current state in memory and transforms against a known history, so OT stays simple and CRDT merging stays cheap. Permission checks, rate limits and snapshots all have one place to run. The costs are a scaling ceiling per document, extra latency for distant users, and a failover gap when the owner dies. These are acceptable because a single document's edit rate is human-bounded and small, and leases with fencing make failover safe. Multi-writer designs remove the hotspot but need consensus or full CRDT semantics everywhere, which is more complexity than most products need.
17In an OT client, what does it do with local edits while it is waiting for an acknowledgement?Very often asked
The classic design, from Jupiter and used by Google Wave, keeps at most one op in flight. While waiting for its ack, new local edits are composed into a single buffer op. When a remote op arrives, the client transforms it against both the in-flight and buffered ops before applying it, and also transforms those pending ops so they stay valid. When the ack arrives, the buffer becomes the next in-flight op. This keeps the server's transform simple, because each client op is based on a revision the server knows. It also batches naturally: fast typing during a slow round trip becomes one op, not dozens.
18How do comments stay attached to the right text when the surrounding text is edited or deleted?Often asked
A comment is anchored to stable positions, not raw character offsets. With a CRDT, the start and end are element IDs, so inserts before them do not change the anchor. With OT, the anchor range is transformed through every op just like a cursor. When the anchored text is partly deleted, the range shrinks to whatever remains. If it is fully deleted, the comment becomes orphaned: it is kept in the thread list and shown as 'original text deleted' rather than silently removed. Undoing the deletion should restore the anchor, which CRDT tombstones make straightforward. The comment body, replies and resolution state live in a separate store, so comment edits do not bloat the document log.
19How do you render remote cursors in the right place when edits keep arriving?Often asked
A remote cursor is just a position, so it has to move with the text. In OT, each client transforms every cached remote cursor offset through incoming and local ops. In a CRDT, the cursor is expressed as an element ID plus a side, so it stays correct without transformation. Presence messages carry the sender's revision, so the receiver can transform a slightly stale cursor up to its own state, or drop it if it is too old. Updates are throttled and coalesced so only the latest position matters. Entries expire on a short TTL, which makes cursors from closed tabs disappear. Each cursor's colour and name come from the session roster, not from the op log.
20How do you handle conflicting rich-text formatting, such as one user bolding a range while another inserts text inside it?Often asked
Plain-text algorithms are not enough. Formatting should be stored as marks anchored to the start and end positions, not as per-character flags copied at write time. Each mark type needs a defined expansion rule. Bold usually grows to include text typed at its end, while a link usually does not. Concurrent conflicting marks, such as bold and unbold on overlapping ranges, need a deterministic winner, often decided by a Lamport timestamp. Every replica then resolves the conflict the same way. The Peritext work from Ink & Switch describes these issues for CRDTs. With OT, you define transform functions for format ops against inserts and deletes. Either way, I would fuzz-test formatting heavily because the edge cases are subtle.
21How would you implement suggestion mode, where a commenter proposes edits?Often asked
A suggestion is an edit that is recorded but not yet accepted. I would represent it as ops tagged with a suggestion ID and author, so the text appears with strike-through or a highlight but is marked provisional in the model. Because they are real ops anchored to the same positions, suggestions move with concurrent edits exactly like normal text. The server allows commenter-role users to create only suggestion-tagged ops and rejects plain edits from them. Accepting a suggestion appends an op that clears the tag. Rejecting it appends ops that remove the inserted text and restore any deleted text. Both are logged, so history shows who proposed and who approved each change.
22What should the server do when a reconnecting client is very far behind?Often asked
Replaying thousands of missed ops can be slower than sending fresh state, and in OT it also means transforming the client's pending queue against all of them. The server compares the gap with a threshold. Beyond it, the server sends the latest snapshot plus a short tail instead. The client keeps its unacknowledged local ops, rebuilds from the snapshot and then rebases or merges its queue on top. If tombstones before the client's version have been garbage-collected, a direct merge may no longer be possible. The client then computes a diff between its local text and its last known base and resubmits that diff as new ops. The user's work survives, even if fine-grained intent is slightly reduced.
23What metrics and SLOs would you set for this system?Often asked
The key user-facing SLI is op acknowledgement latency at p50 and p99, measured from client send to ack, because it reflects durability and server health. Next comes remote propagation latency: time from one user's ack to another user's render. I would track document load time split into snapshot fetch and tail replay, plus the average replay length, which tells me if compaction is falling behind. On reliability: reconnect rate, ops rejected, idempotent duplicates seen, and fencing rejections, which are a split-brain warning. Most important is a convergence check: clients periodically send a hash of their state at a revision, and any mismatch triggers an alert and a forced resync.
24How do you test that every replica actually converges?Often asked
Unit tests are not enough, because bugs hide in rare interleavings. I use property-based fuzz testing. Spin up several simulated replicas, generate random inserts, deletes and format ops, deliver them in random orders with delays, duplicates and disconnects, then assert all replicas end with identical state. For OT, I also verify the transform properties directly on random op pairs. Failing cases are shrunk to minimal reproductions. In production, clients periodically report state hashes at known revisions, catching bugs the fuzzer missed. Chaos tests kill session servers mid-write and check that no acknowledged op disappears. Keeping the same core library on client and server ensures tests exercise the real code.
25How would you handle a document with thousands of viewers, such as a company-wide announcement?Often asked
Viewers send no edit ops, so the challenge is fan-out, not merging. I separate viewer traffic from editor traffic. Editors stay on the owning session server's path. Viewers attach to a broadcast tier: the fan-out channel feeds relay nodes that push ops to many read-only connections. Each relay holds a recent op buffer, so a lagging viewer can catch up without touching the session server. Presence for viewers is aggregated into a count rather than individual cursors, which removes most of the traffic. Initial loads come from a cached snapshot. If ops arrive faster than viewers can render, relays can batch them or send periodic snapshots, because viewers do not need every intermediate state.
26How do you protect document contents in transit and at rest, and could you offer end-to-end encryption?Often asked
In transit, everything runs over TLS, including service-to-service links, with mutual TLS inside the cluster. At rest, the log, snapshots and comments are encrypted with keys from a KMS, often using per-tenant keys so an enterprise customer can revoke access. Access to raw data is audited and restricted to break-glass roles. End-to-end encryption is harder. Classic OT needs the server to read ops to transform them, so it conflicts with E2E. A CRDT design can work because the server only orders and relays ciphertext. You lose server-side features, though: search indexing, previews, snapshots built by the server, and permission checks based on content. That is a real trade-off to discuss with product.
27How do you choose the snapshot interval, and how do you trust a snapshot?Often asked
The interval trades load speed against write and storage cost. Frequent snapshots mean short replays on open but more large writes. Rare snapshots mean long replays. I usually trigger on a mix of op count, accumulated bytes and time since the last snapshot, so busy and quiet documents are both handled. The compactor runs off the hot path. It builds the snapshot by replaying the log, stores it with its revision and a checksum, and only then updates the document's latest snapshot pointer. Older snapshots can be thinned out for history. To build trust, I periodically verify that a snapshot plus replay matches a fresh replay from an earlier snapshot.
28How do you protect the system from buggy or malicious clients sending bad ops?Often asked
I never trust the client. The session server validates every op against a schema: positions within bounds, known op types, sizes under limits, valid element IDs, and a supported format version. Invalid ops are rejected with an error that forces the client to resync from a snapshot, rather than being partly applied. Permissions are checked server-side for every op, including formatting and comment ops. Per-user and per-document rate limits stop floods. Text content is sanitised before rendering in other users' browsers to prevent XSS through pasted HTML or links. If a client keeps producing invalid ops, its session is closed and the event logged, because that usually means a bug or tampering.
29What do you do about slow consumers on the fan-out path?Often asked
A client on a poor mobile connection must not slow everyone else. Each gateway keeps a bounded outbound buffer per connection. Presence messages are dropped first when it fills, since only the latest cursor matters. Ops are never dropped silently: if the buffer overflows, the gateway closes or flags the connection, and the client resyncs from its last revision using the log or a snapshot. The session server publishes once to the channel and never waits for individual clients. Gateways can also coalesce several queued ops into one frame. Monitoring buffer depth and forced resyncs per connection shows network trouble before users complain.
30How do you handle very large pastes or very large documents?Sometimes asked
A huge paste should not become one giant message that blocks the session. The server enforces a maximum op size and the client splits large inserts into chunks that share a paste ID, so they still undo as one action. Images and attachments go to object storage through a separate upload, and the document holds only a reference. For very large documents, the client loads incrementally: it fetches the snapshot structure and renders the visible portion first. Snapshots may be split by section so compaction does not rewrite everything. There are also hard per-document limits on size and ops per second per user, which protect shared infrastructure from abuse or runaway scripts.
31How do you handle deletion requests and data retention, for example under India's DPDP Act?Sometimes asked
Deleting a document is harder than deleting one row, because its content lives in the log, snapshots, search index, caches, backups and notification payloads. I would soft-delete first, moving the document to trash for a recovery window. A hard delete then removes log partitions, snapshots and comments, and sends deletion events through the change feed so search and other downstream systems purge their copies. Backups age out on a documented schedule. Crypto-shredding helps here: if each document or tenant has its own key, destroying the key makes residual copies unreadable. Retention policies and legal holds must override user deletion where the law requires, and the policy should be reviewed with legal counsel.
32How does the change feed keep search indexing up to date, and how fresh does it need to be?Sometimes asked
The log, or a CDC stream from it, publishes committed ops with doc ID and revision. An indexer consumes them, but re-indexing per keystroke is wasteful, so it debounces per document. After a quiet period, or every few minutes during active editing, it loads the current text and re-indexes the whole document at that revision. Storing the indexed revision lets it skip stale work and stay idempotent when it replays the feed. Search is eventually consistent, and users tolerate short delays. Permissions matter more than freshness: the index stores ACL metadata, results are filtered at query time against the current ACL, and ACL changes trigger prompt index updates.
33How do you roll out a new op format without breaking clients that have not updated?Sometimes asked
Every op and snapshot carries a format version. Servers are deployed first and must read both old and new formats. During the transition, they can down-convert ops for old clients where possible, or ask clients that cannot understand a new feature to refresh. New op types ship behind a flag and are enabled only once nearly all active clients support them, which telemetry confirms. Old ops in the log are never rewritten. Replay code keeps every historical version so version history still works. Offline clients present a special case: on reconnect, they declare their version, and the server either accepts their ops through an upgrade path or requires a reload before they can submit.
Objective questions 33
1At what point may the session server acknowledge an edit to the sending client?Asked almost every time
Why: Acknowledging only after a durable log append is what guarantees an acknowledged edit is never lost. Waiting for other clients or snapshots adds latency without improving durability.
2What is the purpose of a fencing token on the document ownership lease?Asked almost every time
Why: A paused or partitioned old owner may still try to write. A monotonically increasing token lets the log reject its writes, which prevents two different histories.
3Which key best makes op submission idempotent across retries?Asked almost every time
Why: (client_id, seq) uniquely identifies an op from a session, so a resent op can be recognised and given its original revision instead of being applied twice.
4A viewer modifies the client JavaScript to send edit ops. What should happen?Asked almost every time
Why: Authorisation must be enforced server-side for every op. The client can never be trusted to restrict itself.
5User A inserts 'X' at position 5 while user B concurrently deletes the character at position 2. After transformation, where is A's insert applied on B's replica?Asked almost every time
Why: B removed one character before position 5, so A's insert must shift left by one, to position 4, to keep its intended place.
6Why does a classic OT-based editor route all operations through a central server?Very often asked
Why: Many OT algorithms only guarantee convergence when there is one agreed order of operations, which a central sequencer provides. Without it, proving correct transformation for every concurrent combination is very hard.
7Which property of a state-based CRDT merge function guarantees replicas converge regardless of delivery order and duplicates?Very often asked
Why: A join that is commutative, associative and idempotent produces the same result whatever the order of merges and however often an update is redelivered, so all replicas converge.
8Which OT property states that applying O1 then transform(O2, O1) gives the same state as applying O2 then transform(O1, O2)?Very often asked
Why: TP1 requires that two concurrent ops, each transformed against the other, lead to the same document state. TP2 deals with transforming against sequences and matters in decentralised OT.
9How is revision R of a document reconstructed for version history?Very often asked
Why: Snapshots bound the replay length, so any revision loads in roughly constant time relative to the snapshot interval.
10Why do many sequence CRDTs keep tombstones for deleted characters?Very often asked
Why: A concurrent insert may name a deleted character as its neighbour. Keeping the tombstone lets every replica resolve that position the same way.
11In a Jupiter-style OT client, how are local edits handled while one op awaits acknowledgement?Very often asked
Why: Keeping one op in flight and buffering the rest means every op the server sees is based on a revision it knows, which keeps server transforms simple.
12What does strong eventual consistency guarantee for CRDT replicas?Very often asked
Why: Strong eventual consistency means convergence is deterministic once the same updates are delivered, regardless of order, with no conflict resolution rounds.
13How should Ctrl+Z behave in a collaborative document?Very often asked
Why: Undoing others' work is confusing, and rewriting the log breaks history. Selective local undo, sent as a new transformed op, avoids both problems.
14A client receives revision 105 right after applying revision 103. What should it do?Very often asked
Why: Fan-out may be at-most-once. Revision numbers let clients detect gaps and fill them from the durable log so ops are applied in order.
15Without fencing or conditional appends, what can a split brain between two owners cause?Very often asked
Why: Both owners assign revisions independently, so the log and the clients can end up with conflicting histories. That breaks convergence and can lose acknowledged edits.
16Why is end-to-end encryption easier to pair with a CRDT design than with classic server-side OT?Very often asked
Why: Server-side OT transforms require plaintext positions and content. Clients can merge CRDT ops themselves, so the server can relay ciphertext.
17What is the best way to make a role revocation take effect for an open session?Very often asked
Why: Event-driven invalidation applies revocation quickly, and the TTL bounds staleness if an event is missed.
18Where should live cursor and presence data normally be kept?Often asked
Why: Presence changes constantly and has no long-term value, so it stays in memory with a TTL and may be lossy. Persisting it would bloat the op log and slow history replay.
19What can a vector clock tell you that a single Lamport timestamp cannot?Often asked
Why: Lamport timestamps give a total order consistent with causality but cannot reveal concurrency. Vector clocks can show that neither event happened before the other.
20What is the main benefit of consistent hashing when routing documents to session servers?Often asked
Why: With consistent hashing, only keys near the changed node move, which limits disruption when the cluster changes.
21Why are presence updates throttled and given a short TTL?Often asked
Why: Presence is ephemeral. Throttling cuts bandwidth, and a TTL clears cursors from closed tabs without explicit cleanup.
22Why is a WebSocket preferred over periodic HTTP polling for live editing?Often asked
Why: A persistent bidirectional connection avoids polling delay and request overhead, which suits frequent small messages in both directions.
23A client reconnects so far behind that replay would be very slow. What is the best response?Often asked
Why: A snapshot catches the client up cheaply while its unacknowledged local work is preserved and reapplied.
24What is the trade-off of taking snapshots more frequently?Often asked
Why: Shorter intervals shorten replay on load at the cost of more frequent, larger snapshot writes.
25Why is IndexedDB used to queue offline ops rather than localStorage?Often asked
Why: Long offline sessions can produce many ops. IndexedDB stores structured data with far higher limits and does not block the main thread.
26A user far from the document's owning region types. What do they perceive?Often asked
Why: Optimistic local application hides latency for one's own edits. Only server confirmation and remote propagation pay the distance.
27Which primary key layout suits the operation log best?Often asked
Why: Partitioning by document and ordering by revision supports fast tail reads and conditional appends, and keeps a document's history together.
28How is a globally unique element ID typically formed in a sequence CRDT?Often asked
Why: Each replica increments its own counter, so (site_id, counter) is unique without coordination.
29A gateway's outbound buffer for one slow client fills with ops. What is the best action?Often asked
Why: Ops cannot be silently dropped, and one slow client must not stall others. A forced resync from the durable log restores correctness.
30Which metric best reflects whether users' edits are being safely saved?Often asked
Why: The ack includes the durable write. Its latency and failure rate directly show the health of the save path users depend on.
31How should bold formatting be represented so it behaves well under concurrent edits?Sometimes asked
Why: Anchored marks with clear expansion and conflict rules, as in Peritext, give consistent results when text is inserted at or within the range.
32What makes garbage-collecting CRDT tombstones safe?Sometimes asked
Why: Removing a tombstone before all replicas have seen it can break the placement of concurrent inserts. Long-offline clients therefore need a cut-off and a rebase path.
33Restoring an old version from history should do what?Sometimes asked
Why: Appending keeps history immutable and auditable, and the restore itself can be undone. It also never destroys collaborators' later work.
Track your progress through every blueprint in your dashboard.
Start learning