# Multiplayer Collaborative Canvas

**Solution Architecture v1.0 · Microsoft Azure · Platform Architecture · 2026-10 · 23 views · 17 architecture decision records**

Two designers open the same file and start moving the same frames. Every product that has solved this — Figma and FigJam, Google Docs, Notion, Canva, Miro — is judged on it without mercy: an editor that loses a stroke, double-applies a drag, or shows two people different versions of the same frame is not a slow product, it is a broken one. This package is the multiplayer backend behind such a canvas: an assumed 4 million monthly active editors and 11 million viewers, 300,000 concurrently connected clients at peak, 120,000 operations a second with a 3.3× burst, 1.5 million presence messages a second after coalescing, and 900 million documents whose p99 is 60 MB — built on AKS session hosts that own both the socket and the sequencer, Cosmos DB as a per-document append-only operation log, Blob Storage for checkpoints and content-addressed assets, Azure Web PubSub for the traffic that is allowed to be lost, and Entra ID with Key Vault HSM for the authority that is not.

The hard part is not the merge. It is that four requirements pull in opposite directions at once: the edit must feel instant, so the client cannot wait for a server; the document must converge, so something must decide the order; work done on a train must survive, so the client must be allowed to run ahead for hours; and a revoked collaborator must stop editing in seconds, so the server must be able to say no to a socket that is already open.

The design rests on one rule: **each document has exactly one authoritative sequencer at a time, and every client is a speculative replica of it — the client renders first and the server decides last.**

The decisions that carry the design:

- **One sequencer per document; clients are speculative replicas.** The client renders an edit before any server has seen it and the host's order is final. That buys small intent-shaped operations, a plain append-only history, per-user undo that means what a user expects, and one implementation of the conflict rules instead of one per client platform — at the price of an authority that must be leased, fenced and failed over (ADR-01).
- **An operation is acknowledged on durability, never on receipt.** The append commits and replicates in-region before the acknowledgement, which makes RPO 0 for everything the user was told was safe. The corollary is the unpopular one: when the log cannot be written, the document goes read-only within 5 seconds rather than collecting edits it may lose (ADR-04).
- **Ownership is a lease with an epoch, fenced at the store.** A 15-second lease with a monotonic epoch, and a log that rejects any append carrying an older epoch, makes transient double-ownership harmless instead of catastrophic. That is what allows a cheap lease rather than a consensus round on every operation (ADR-03).
- **Operations describe intent, never rendered diffs.** Create, delete, reparent, set property, reorder — the only unit from which history, merge, per-user undo and attribution all follow, and the reason a document written in 2026 can be opened by a renderer nobody has written yet (ADR-02).
- **Editors terminate on the sequencer; viewers and presence do not.** The socket and the sequencer share a process, so an acknowledgement costs one hop, while 1,000 viewers on a popular document consume none of the capacity of the node that orders its edits (ADR-06).
- **Presence is sacrificial.** Coalesced server-side to 10 Hz whatever the client sends, never written anywhere, retained for zero seconds, and the first thing shed under load. It is the highest-volume and least valuable traffic in the platform, and treating it as a cheap edit is how collaborative editors end up with cursors competing with keystrokes (ADR-07).
- **The per-document log is the record, in a partitioned document store rather than a broker.** 900 million mostly-idle logs are a key-space problem, not a throughput one: a free idle partition, a conditional append that also enforces the fence, and a keyed range read (ADR-09).
- **The session writes its own checkpoint; a verifier disagrees with it.** One implementation of document application on the write path, because a second one is a second set of bugs — and an independent rebuild that replays the log and diffs the result, which is how a one-way application bug is found before a user finds it (ADR-10).
- **Restore is a forward operation and history is never rewritten.** A restore makes the document equal to an earlier state by emitting operations, so live clients see a large edit rather than a disconnection, and no comment anchor or audit record can dangle (ADR-11).
- **Offline work is rebased, branched, or reported — never silently dropped.** Buffered operations are rebased under the live conflict rules inside the 30-day log horizon and preserved as a recoverable branch beyond it. The one outcome the platform refuses to produce is a silent loss (ADR-12).
- **Assets move out of band, content-addressed, valid before the bytes arrive.** A 90 MB paste costs the document a few hundred bytes of ordering work, at the price of a pending state the product renders honestly (ADR-13).
- **Capability is bound at admission and revocation bites on a live socket.** Grant changes reach affected sessions within 10 seconds; during a control-plane outage, open sessions continue on a 5-minute cached grace window and new admissions fail closed (ADR-14).
- **Convergence is a release gate, and a rollout is a drain.** The same operation set in randomised orders must produce byte-identical documents, and a live session never changes code version — a release waits for documents to be released rather than hot-swapping the code that owns one in memory (ADR-05, ADR-17).
- **Divergence is detected by the platform, not reported by users.** Clients periodically prove they agree with the authority at a known sequence; a mismatch alerts within 60 seconds and is repaired by re-snapshot. It is the only failure class with no natural alarm (ADR-17).
- **One home region per document.** Active-active editing would mean two sequencers, which is the one thing this architecture forbids. Cross-region is a migration with an announced pause, and a regional failover is a declared operation with a 5-second loss window stated to users (ADR-16).

The architecture one-pager (including why the design should still hold up in ten years, and the six risks that would change it) and the full decision record appear on the landing page of the diagram set, directly below the index of views. The same content is published as [docs/architecture-one-pager.md](docs/architecture-one-pager.md) (~14 min) and [docs/decision-record.md](docs/decision-record.md) (~63 min).

---

## What is here

| Path | Contents |
|---|---|
| `diagrams/index.html` | The landing page: 23 views in seven acts with every format linked, then the **architecture one-pager** and the **decision record** |
| `diagrams/*.html` | One self-contained page per view: the inlined diagram plus the reasoning cards, with copy / PNG / PDF export |
| `diagrams/svg/*.svg` | The same views as SVG with the diagram XML embedded; they re-open fully editable in diagrams.net |
| `diagrams/drawio/*.drawio` | draw.io source |
| `docs/architecture-one-pager.md` | The one-pager as markdown |
| `docs/decision-record.md` | The seventeen decision records, the stack table and the glossary as markdown |
| `ask.md` | The requirement this package answers |
| `specs/part-*.json`, `specs/manifest-*.json`, `specs/adr-*.json` | The authoring sources. Edit these, never the assembled `views.json`, `manifest.json` or `adr.json` |
| `scripts/build.sh` | Rebuilds every deliverable from the specs. Node 20+, no network, no draw.io Desktop |

## Rebuilding

```bash
cd architecture/deliverables/use-cases/multiplayer-collaborative-canvas
bash scripts/build.sh
```

The build generates draw.io from the specs, fails on overlapping geometry or an arrow crossing a box, renders both SVG forms, writes the HTML pages and index, injects the one-pager and decision record, and proves every relative link resolves. The current set passes with **0 errors and 0 warnings** on both gates — 23 files, 150 edges routed, 331 nodes all iconed.

## The seven acts

| # | Act | Views |
|---|---|---|
| 1 | Context and scope | 01–02 |
| 2 | People and journeys | 03–06 |
| 3 | Structure | 07–09 |
| 4 | Data | 10–12 |
| 5 | Runtime | 13–16 |
| 6 | Operations | 17–20 |
| 7 | Assurance | 21–23 |

## Evidence

This is a design, not a report on a running system. Every rate, latency, interval, limit and retention figure in `ask.md`, on the cards and in the records is a **stated assumption**, chosen to be defensible and arguable rather than measured. Nothing here is drawn from the internals of any named product; the products in the opening paragraph are there because they make the problem recognisable, not because this is how they are built.
