Skip to content

Figma#

Problem statement (interviewer prompt)

Design Figma's multiplayer canvas: many users collaboratively edit a vector design file with shapes, components, prototypes, and comments. Cover the CRDT model, server-side document state, multiplayer cursors, undo/redo, version history, and plugin runtime.

flowchart LR
  A[Editor A]
  B[Editor B]
  WS[Realtime Engine<br/>per file]
  ST[(Object tree + history)]
  CDN
  A --> WS --> B
  WS --> ST
  CDN --> A

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class A,B,WS service;
    class ST storage;
flowchart TB
  subgraph Clients
    APP([Figma client - WebGL])
    PRES[Presence + cursors]
  end

  subgraph Edge
    LB
    WS[WebSocket gateway]
  end

  subgraph Engine[Multiplayer engine]
    SVR[Per-file server<br/>single owner]
    CRDT[Custom CRDT-ish merge<br/>object tree + properties]
    OPS[[Op stream]]
    SNAP[Snapshots]
    PRES_SVC[[Presence pub/sub]]
  end

  subgraph Storage
    OBJ[(Object tree per file)]
    HIST[(Version history)]
    ASSET[(Image assets + S3 + CDN)]
    FONTS[Fonts service]
    THUMB[Thumbnail renderer]
  end

  subgraph Features
    COMM[Comments]
    PLUG[Plugins / Widgets]
    LIB[Components / styles libraries]
    DEV[Dev mode + inspect]
    PROTO[Prototyping]
  end

  subgraph Share
    PERM[Permissions / teams / projects]
    AUTH[SSO / SCIM]
  end

  Clients --> Edge --> Engine
  Engine --> Storage
  Features --- Engine
  Share --- Storage

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class APP client;
    class WS edge;
    class PRES,SVR,CRDT,SNAP,FONTS,THUMB,COMM,PLUG,LIB,DEV,PROTO,PERM,AUTH service;
    class HIST datastore;
    class OPS,PRES_SVC queue;
    class OBJ,ASSET storage;

Per-file owner#

  • File "lives" on one process at a time → linearizes mutations.
  • Migrations between hosts via op-log replay.
  • Designed for tens of editors per file.

Asset handling#

  • Images stored in S3 + CDN.
  • Vector geometry lives in the in-memory object tree synced via ops.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD CDN edge caching for static assets cdn
HLD Pub/Sub & message brokers topics, consumer groups, delivery semantics pub-sub-pattern
HLD CRDTs commutative replicated data types crdts
HLD Realtime protocols WS / SSE / polling / gRPC streaming realtime-protocols

Quick reference#

Functional#

  • Real-time multiplayer canvas.
  • Cursors, comments, history.
  • Components / styles / libraries.
  • Prototyping + Dev mode.
  • Plugins.

Non-functional#

  • Op echo < 200 ms locally.
  • Tens of editors per file.
  • 99.95% uptime.

Trade-offs#

  • Single owner per file simplifies; needs migration on failover.
  • Custom CRDT because graphics tree has parent/child + property merge semantics.
  • WebGL client offloads rendering; server is purely state engine.

Refs#

  • Figma engineering blog ("How Figma's multiplayer technology works").
  • Yjs design comparisons.
  • ByteByteGo "Design Figma".

FAQ#

How does Figma's multiplayer work?#

Each open file runs a dedicated realtime engine that holds the object tree in memory. Clients send incremental ops over WebSocket; the engine merges them with CRDT semantics and broadcasts to all editors.

Why does Figma use a CRDT model?#

Designs are a tree of properties where concurrent edits like move and resize must converge predictably. A CRDT per property lets users edit offline and reconnect without conflict prompts.

How does Figma sync vector graphics in real time?#

Vector shapes are stored as nodes with property maps. Updates send only the changed property deltas, so dragging a shape sends a position update at 60Hz rather than the whole object.

How are multiplayer cursors implemented in Figma?#

Cursors are ephemeral presence data broadcast on a side channel of the same WebSocket. They are not persisted, only relayed to current viewers at a throttled rate.

How does Figma store version history?#

The engine snapshots the object tree periodically and stores an immutable diff log. Users can branch off any snapshot to recover an older state without rewriting current history.

Video walkthrough

From Google Docs to Figma: OT vs CRDT Trade-offs : via System Design Walkthrough