Case: Figma's Multiplayer Server, CRDT-Inspired but Not Quite
Era: 2017 to present · Author / source: Figma blog, "How Figma's multiplayer technology works" (Evan Wallace, 2019); Figma blog, "Rust in production at Figma" (2022) · Read alongside: CRDTs, operational transforms, last-writer-wins, fractional indexing
The situation
Figma's product proposition is real-time multi-user vector design in the browser. Multiple designers edit the same document at the same time, see each other's cursors, and never block each other. The competitor reference point in 2015-2017 was Google Docs, which uses operational transformation (OT). The other reference point was the academic CRDT literature, which had matured but still carried serious overhead in practice.
The technical situation differed from Google Docs in two important ways. First, Figma documents are not linear text; they are trees of objects (frames, layers, components, instances), each with many properties (position, color, opacity, transform, parent reference). Second, Figma had a server in the loop from day one; it was not designed as a peer-to-peer system. That single fact opens architectural choices that pure CRDT systems do not have.
The design needed to deliver: low-latency client-side response (changes apply locally without waiting for the server), eventual convergence across clients, no lost updates, no resurrected deleted objects, and operability by a small team. The original implementation was a TypeScript server, and as documents and concurrent-user counts grew, that server became the latency bottleneck.
The options on the table
- Operational Transformation (OT), Google Docs style. Each client transforms incoming operations against locally-applied operations. Provably correct for text; gets hairy for tree-structured data with arbitrary properties.
- True CRDTs. Each operation is independently commutative; clients converge without coordination. Strong guarantees, peer-to-peer friendly, but the data structures carry significant memory and bandwidth overhead and the property of "no central authority" is overkill when you have a server anyway.
- CRDT-inspired with a central server. Treat the server as the authority. Use CRDT-style per-property convergence rules (last-writer-wins by timestamp, fractional indices for list positions), but skip the parts of CRDT machinery that exist only to handle the peer-to-peer case.
- Server-arbitrated with manual conflict resolution. Whoever writes second sees a "you have a conflict" dialog. Defensible for code; product-killing for design.
- Naive last-write-wins on whole-document level. Trivial to implement, destructive on every concurrent edit. Useful only for low-collaboration tools.
What they chose, and why
Option 3: CRDT-inspired but explicitly not full CRDTs. Figma's blog says this directly. They considered "operational transforms (a.k.a. OTs), the standard multiplayer algorithm popularized by apps like Google Docs," and concluded "OTs were unnecessarily complex for our problem space." They moved to a model "inspired by something called CRDTs" but, crucially, "Figma isn't using true CRDTs." The reason given: because Figma has a server, "we can simplify our system by removing this extra overhead and benefit from a faster and leaner implementation."
The mechanics:
- Documents are object trees. "A tree of objects, similar to the HTML DOM," with parent-child relationships maintained through property links.
- Server is the authority. Quoted verbatim: "the server is the ultimate authority on what the document looks like." Clients apply changes locally for responsiveness, but the server arbitrates.
- Per-property last-writer-wins. "Figma's multiplayer servers keep track of the latest value that any client has sent for a given property on a given object." The granularity matters: it is not last-write-wins on the whole object, it is last-write-wins on each property. Two designers changing the fill color and the position of the same rectangle do not stomp each other.
- Fractional indexing for list positions. Position within a parent's children array uses fractional indices, so two inserts between the same neighbors do not collide; they get adjacent fractional values and the order stabilizes after the server arbitrates.
The implementation evolved. The original TypeScript multiplayer server was single-threaded and "couldn't process operations in parallel," which meant a heavy document-encoding step would lock up the worker. Figma rewrote the performance-critical portion in Rust. The hybrid model is documented: the Node.js process still handles network I/O, but it spawns a Rust child process per document, communicating via stdin/stdout. The result, per Figma's writeup, was serialization "over 10x faster than the original TypeScript implementation," with substantial latency improvements.
What they gave up
- Offline editing. A true CRDT system, with peer-to-peer convergence, would let two clients edit while disconnected and merge cleanly on reconnect. Figma's server-arbitrated model is online-first; offline support, when it exists, is constrained.
- Provable convergence guarantees. Real CRDTs come with mathematical convergence proofs. Figma's design is correct in practice but does not carry those guarantees in the same form.
- Hot-swap of the multiplayer authority. The server is the source of truth. If a server goes down for a document, that document's session pauses until failover.
- A pure language stack. The Rust + Node.js split introduces FFI, deployment complexity, and a debugging surface. Figma writes about the lifetime complexity, lack of stack traces in Rust panics, and the immature async story at the time. They paid these costs because the alternative (a fully TypeScript server) had hit its performance ceiling.
- CRDT ecosystem compatibility. Library writers in the CRDT space cannot trivially interoperate with Figma's format because it is not a standard CRDT.
How it played out
Figma became the dominant collaborative design tool. The multiplayer experience is widely cited as a differentiator versus Sketch, which was single-player by design. Adobe announced a $20 billion acquisition of Figma in 2022; the deal was terminated in 2023 after regulatory pushback. The multiplayer architecture was named by analysts as a core piece of the asset.
The Rust rewrite delivered the published gains. Memory consumption dropped enough to allow one Rust process per document, replacing the prior shared-worker model. Latency tails improved. The hybrid Node.js + Rust deployment remains in production.
The CRDT-inspired model has been studied and partially imitated by other collaborative tools (Linear, Notion, Pitch). The lesson many teams extracted: if you have a server, you do not have to pay the full CRDT tax. Per-property last-writer-wins plus fractional indices covers most of the use cases that matter.
Where it ties to this bank's patterns
- [[crdts]]: the theory Figma drew from, but did not fully adopt.
- [[operational-transformation]]: the alternative Figma explicitly rejected.
- [[last-writer-wins]]: the conflict resolution primitive, applied at property granularity.
- [[fractional-indexing]]: the list-ordering trick that avoids collision on concurrent insert.
- [[server-as-authority]]: the architectural pattern that lets you skip the harder CRDT machinery.
- Problem links: collaborative editor design, real-time whiteboarding, distributed document state.
What a candidate should take away
- CRDTs are a vocabulary, not a religion. The right answer is often "borrow the parts that fit, skip the parts that do not."
- The presence or absence of a central authority changes the design substantially. Server-arbitrated systems do not need to solve the hardest CRDT problems.
- Conflict granularity matters. Last-writer-wins per property is a different product than last-writer-wins per object. Pick the granularity that matches user intent.
- Fractional indices solve the most boring conflict (list insert order) with the least machinery. Many collaboration bugs trace back to integer indices.
- Performance ceilings drive language migration, not aesthetics. Figma did not rewrite TypeScript in Rust because Rust is fashionable; they rewrote it because the TS server couldn't process operations in parallel.
What an AI agent would not have got right
- An AI asked to "build a multiplayer design tool" will reach for either OT or full CRDTs, because those are the textbook answers. The hybrid pragmatic design is harder to invent without specific context.
- It will conflate convergence and consistency. The default sketch will offer either strong consistency (and lose responsiveness) or eventual consistency (and lose authority), missing that "server-arbitrated with optimistic local apply" is its own coherent point on the spectrum.
- It will pick whole-object granularity for last-writer-wins, which is wrong. The per-property granularity is what makes simultaneous edits non-destructive.
- It will not propose fractional indices for list positions. Integer positions with conflict-on-collision is the default, and it is the single biggest source of multi-user editing bugs.
- It will probably not anticipate the multi-language deployment cost. AI tends to under-cost language interop, debugging surface, and FFI complexity.
Sources
- Figma blog, "How Figma's multiplayer technology works" (Evan Wallace, 2019): https://www.figma.com/blog/how-figmas-multiplayer-technology-works/
- Figma blog, "Rust in production at Figma" (2022): https://www.figma.com/blog/rust-in-production-at-figma/