Skip to content

Online Whiteboard (Miro / Excalidraw)#

Problem statement (interviewer prompt)

Design an online whiteboard (Miro / Excalidraw): users collaboratively place shapes + arrows + sticky notes + freehand strokes on an infinite canvas. Handle 100+ concurrent editors per board, multiplayer cursors, undo/redo, exports, and embeds.

flowchart LR
  A([User A])
  B([User B])
  WS[Realtime engine]
  ST[(Scene state)]
  A --> WS --> B
  WS --> ST

    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 client;
    class WS service;
    class ST datastore;
flowchart TB
  subgraph Clients
    CV([Canvas client])
    CUR[Cursors]
    TOUCH[Touch / stylus]
  end

  subgraph Edge
    WS[WebSocket]
  end

  subgraph Engine
    SVR[Per-board server]
    CRDT[CRDT - shapes + properties]
    OPSTREAM[[Op stream]]
    PRESENCE[[Presence pub/sub]]
    SNAP[Snapshots]
  end

  subgraph Storage
    BOARD[(Board state)]
    HIST[(History)]
    ASSET[(Image / sticker assets + CDN)]
  end

  subgraph Features
    TPL[Templates]
    VOTE[Voting / dot voting]
    TIMER[Timer]
    EMBED[Embedded media / iframes]
    EXPORT[Export PNG / PDF]
    INF[Infinite canvas, zoom]
  end

  Clients --> WS --> Engine --> Storage
  Features --- Engine

    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 CV client;
    class CUR,TOUCH,WS,SVR,CRDT,SNAP,TPL,VOTE,TIMER,EMBED,EXPORT,INF service;
    class BOARD,HIST,ASSET datastore;
    class OPSTREAM,PRESENCE queue;

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#

  • Infinite canvas with shapes, text, images, sticky notes.
  • Multi-user with cursors.
  • Templates, voting, timer, embeds.
  • Export, comments.

Non-functional#

  • Op echo < 200 ms.
  • Many concurrent editors per board.
  • Large boards (10k+ elements) must scroll smoothly.

Trade-offs#

  • Per-board owner simplifies; failover requires replay.
  • Vector elements stream as ops; raster assets via CDN.
  • Excalidraw is open-source and CRDT-friendly; Miro is closed.

Refs#

  • Excalidraw architecture (open source).
  • Miro engineering posts.
  • ByteByteGo "Design collaborative whiteboard".

FAQ#

How does an online whiteboard like Miro work?#

Each board runs a realtime engine that owns a scene graph of shapes. Clients send shape ops over WebSocket, the engine merges with CRDT, and broadcasts deltas to all collaborators.

How do you handle 100+ concurrent editors on one board?#

Shard the board into spatial tiles so only viewers of the visible tile receive its updates. Throttle cursor pings to 20Hz and coalesce shape ops in a 50ms window before broadcast.

How are freehand strokes synced in real time?#

Strokes stream as point batches every few frames so other clients see the draw in progress. The final stroke is committed once the pen lifts and the buffered batch is collapsed.

How do whiteboards export to PDF or image?#

A headless renderer reads the scene state, lays it out at the chosen DPI, and emits PNG, SVG, or PDF. Exports run as background jobs because large boards can take seconds.

How is undo and redo implemented?#

Each client keeps a local op history and pushes inverse ops on undo. The remote engine accepts inverse ops like any other op so undo participates in the same CRDT merge.

Video walkthrough

Design Whiteboard (Excalidraw/Figma/Draw.io): HLD Mock Interview : via Chakde System Design