Interactive architecture map of Figma's engineering systems — rendering engine, multiplayer collaboration, plugin sandbox, and infrastructure compiled from publicly available sources.
Figma is a browser-based collaborative design tool built on a hybrid C++/TypeScript architecture. The rendering engine runs in WebAssembly, real-time collaboration flows through Rust multiplayer servers over WebSockets, and plugins execute in a Realms-based sandbox on the main thread.
graph TD
subgraph Client["Browser Client"]
UI["TypeScript + React UI"]
WASM["C++ / WebAssembly Engine"]
GPU["WebGL / WebGPU Renderer"]
end
subgraph Server["Multiplayer Infrastructure"]
RUST["Rust Multiplayer Server"]
WS["WebSocket Transport"]
end
subgraph Storage["Persistence Layer"]
S3["Amazon S3
(file checkpoints)"]
DDB["DynamoDB
(write-ahead log)"]
RDS["PostgreSQL
(metadata, sharded)"]
end
subgraph Plugins["Plugin System"]
REALM["Realms Sandbox
(main thread)"]
IFRAME["iframe
(plugin UI)"]
end
UI --> WASM
WASM --> GPU
UI --> WS
WS --> RUST
RUST --> S3
RUST --> DDB
RUST --> RDS
UI --> REALM
REALM --> IFRAME
style UI fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style WASM fill:#1a1a3e,stroke:#7c3aed,color:#f0f0f0
style GPU fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style RUST fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style WS fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style S3 fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style DDB fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style RDS fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style REALM fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
style IFRAME fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
Figma's rendering engine is written in C++ and compiled to WebAssembly via Emscripten for the browser, or natively to x64/arm64 for server-side rendering and testing. It bypasses the browser's HTML pipeline entirely, drawing directly to the GPU.
The engine originally compiled C++ to asm.js (a strict subset of JavaScript), then migrated to WebAssembly in 2017 -- cutting load time by 3x regardless of document size. Wasm is still limited to 32-bit addressing (4GB max memory) with a grow-only memory model.
graph LR
subgraph Source["C++ Source"]
CPP["C++ Renderer
(curves, blurs, masks)"]
end
subgraph Compile["Compilation"]
EMC["Emscripten"]
NAT["Native x64/arm64"]
end
subgraph Browser["Browser Runtime"]
WASM["WebAssembly Module"]
GL["WebGL 2.0"]
WGPU["WebGPU"]
end
subgraph Output["Canvas Output"]
TILE["Tile-based
GPU Rendering"]
end
CPP --> EMC
CPP --> NAT
EMC --> WASM
WASM --> GL
WASM --> WGPU
GL --> TILE
WGPU --> TILE
style CPP fill:#1a1a3e,stroke:#7c3aed,color:#f0f0f0
style EMC fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style NAT fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style WASM fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style GL fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style WGPU fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style TILE fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
Figma upgraded from WebGL to WebGPU after Chromium shipped support in 2023. Key improvements include compute shaders that move work from CPU to GPU (e.g., blur rendering), WGSL shading language replacing GLSL, MSAA support, and explicit draw-call arguments with uniform buffer batching.
Custom GPU renderer handles curves (Loop-Blinn algorithm), images, blurs, masking, blending, dithered gradients, blend modes, and nested layer opacity -- all fully anti-aliased.
WebGPU compute shaders move blur rendering and other expensive operations from CPU to GPU, significantly improving performance on supported devices.
Because Figma built its own renderer, it also had to build custom color pickers, text layout engines, and other UI primitives browsers normally provide.
Despite running in a browser, Figma's renderer was often faster than competitors' native applications, thanks to direct GPU access and aggressive tile-based optimization.
Figma uses a client/server model where clients connect via WebSockets to a cluster of Rust servers. Each multiplayer document gets its own server process, and all editors of that document connect to the same process.
Figma chose neither pure Operational Transforms (OT) nor pure CRDTs. Instead, they built a custom system inspired by CRDTs but simpler. Every document is a tree of objects (similar to the HTML DOM) with a single root node. Each object's properties use last-writer-wins (LWW) semantics.
graph TD
subgraph Clients["Editor Clients"]
C1["Client A
(browser)"]
C2["Client B
(browser)"]
C3["Client C
(browser)"]
end
subgraph Transport["Network"]
WS["WebSocket
33ms intervals"]
end
subgraph Server["Multiplayer Server (Rust)"]
AUTH["Validate &
Resolve Conflicts"]
STATE["In-Memory
Document State"]
KIWI["Kiwi Binary
Serialization"]
end
subgraph Persist["Persistence"]
WAL["DynamoDB
Write-Ahead Log"]
SNAP["S3 Checkpoint
(30-60s)"]
end
C1 --> WS
C2 --> WS
C3 --> WS
WS --> AUTH
AUTH --> STATE
STATE --> KIWI
KIWI --> WAL
WAL --> SNAP
AUTH --> WS
style C1 fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style C2 fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style C3 fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style WS fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style AUTH fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style STATE fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style KIWI fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style WAL fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style SNAP fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
Figma uses Kiwi, a custom schema-based binary format created by co-founder Evan Wallace. Similar to Protocol Buffers but simpler and more compact, with better optional field support, variable-length encoding for numeric values, zero-overhead nested structs, and single-scan read/write operations.
The multiplayer server was originally written in TypeScript, then rewritten in Rust for an order-of-magnitude performance improvement. Rust's ownership model helped audit file update paths and ensure journal consistency.
Figma's persistence layer uses Amazon S3 for file checkpoints, DynamoDB for the write-ahead log, and horizontally sharded PostgreSQL for metadata. The architecture treats design files as binary blobs rather than relational data.
graph TD
subgraph Runtime["Multiplayer Server"]
MEM["In-Memory
Document State"]
end
subgraph WAL["Write-Ahead Log"]
DDB["DynamoDB
Journal Entries"]
SEQ["Sequence Numbers
(start, end)"]
end
subgraph Checkpoint["File Checkpoints"]
S3["Amazon S3
Kiwi-encoded .fig"]
end
subgraph Meta["Metadata"]
PG["PostgreSQL (RDS)
Horizontally Sharded"]
LOCK["File Locks
(UUID + file key)"]
end
MEM -->|"every 33ms"| DDB
DDB --> SEQ
MEM -->|"every 30-60s"| S3
MEM --> LOCK
LOCK --> PG
style MEM fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style DDB fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style SEQ fill:#1a1a3e,stroke:#f59e0b,color:#f0f0f0
style S3 fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
style PG fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style LOCK fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
95% of edits are persisted to the write-ahead log within 600ms of the user making a change.
Figma implemented horizontal sharding across PostgreSQL in an 18-month effort, achieving theoretically infinite scalability. One of AWS's largest database customers.
Using a relational database for design file data would abuse it as a filesystem. S3 offers significant cost advantages for file-like access patterns.
Figma plugins use a two-part isolation model: a Realms-based sandbox on the main thread for document access, and an iframe for UI rendering and browser API access. The two parts communicate via postMessage.
graph TD
subgraph MainThread["Main Thread"]
DOC["Figma Document
(scene graph)"]
REALM["Realms Sandbox
(plugin logic)"]
end
subgraph Isolated["Isolated Context"]
IFRAME["Plugin iframe
(HTML/JS UI)"]
NET["Network Access
(fetch, XHR)"]
DOM["DOM Rendering"]
end
subgraph API["Plugin API"]
READ["Read/Write
Document Tree"]
SHOW["figma.showUI()"]
MSG["postMessage
Bridge"]
end
DOC --> REALM
REALM --> READ
REALM --> SHOW
SHOW --> IFRAME
IFRAME --> NET
IFRAME --> DOM
REALM <-->|"postMessage"| IFRAME
style DOC fill:#1a1a3e,stroke:#7c3aed,color:#f0f0f0
style REALM fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
style IFRAME fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style NET fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style DOM fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style READ fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style SHOW fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style MSG fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
Figma considered and rejected several approaches before settling on Realms:
Too slow for document access due to serialization overhead crossing the iframe boundary for every read/write operation.
Also require serialization between threads. No synchronous document access possible from a worker context.
Runs on the main thread with direct access to document objects, but in a sandboxed JS environment that prevents access to globals.
Figma's document model is a tree of objects rooted at a single document node. Components support variants with shared properties, and the Variables system provides a centralized abstract data layer for design tokens.
graph TD
subgraph Primitive["Primitive Layer"]
COL["Color Values
(hex, rgba)"]
SPC["Spacing Values
(px, rem)"]
TYP["Typography
(size, weight)"]
end
subgraph Semantic["Semantic Layer"]
BG["Background
(brand-aware)"]
FG["Foreground
(mode-aware)"]
SPACE["Layout Spacing
(responsive)"]
end
subgraph Usage["Component Layer"]
BTN["Button"]
CARD["Card"]
NAV["Navigation"]
end
COL --> BG
COL --> FG
SPC --> SPACE
TYP --> BTN
BG --> BTN
BG --> CARD
FG --> BTN
FG --> CARD
SPACE --> NAV
SPACE --> CARD
style COL fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
style SPC fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
style TYP fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
style BG fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style FG fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style SPACE fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style BTN fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style CARD fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style NAV fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
Figma completed a major refactoring of the design systems data model. Variable updates and mode switches are 30-60% faster; heavy state swaps improved from 3500ms to 350ms and 2500ms to 450ms.
Variants group similar components into a single container with shared properties (state, size, layout). Properties follow the prop/value format matching frontend frameworks like React and Vue. Forward-slash naming conventions create hierarchical property groupings.
Figma's auto-layout feature ran on two separate layout engines managing different parts of the document with some overlap -- a constant source of subtle bugs that required significant refactoring to unify.
Dev Mode bridges design and engineering with inspect panels, code generation, and Code Connect -- a system that links real codebase components to Figma designs so developers see actual design system code instead of auto-generated snippets.
graph LR
subgraph Design["Figma Canvas"]
SEL["Selected Object"]
end
subgraph Inspect["Inspect Panel"]
TEXT["Text: typography
+ layout info"]
BOX["Other: box model
(margin, border, pad)"]
LANG["Output: CSS,
iOS, Android"]
end
subgraph CodeConnect["Code Connect"]
CCUI["Code Connect UI
(in-Figma, visual)"]
CCLI["Code Connect CLI
(in-repo, mappings)"]
end
subgraph Output["Developer Output"]
REAL["Real Design
System Code"]
MCP["Figma MCP
Server Output"]
end
SEL --> TEXT
SEL --> BOX
TEXT --> LANG
BOX --> LANG
CCUI --> REAL
CCLI --> REAL
REAL --> MCP
style SEL fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style TEXT fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style BOX fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style LANG fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style CCUI fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
style CCLI fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
style REAL fill:#1a1a3e,stroke:#ec4899,color:#f0f0f0
style MCP fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
Plugins can extend Dev Mode's code generation. They appear in the native language dropdown, and the figma.codegen.on("generate") callback fires on selection changes.
Inspection plugins pull context from external tools like Jira, Linear, or Storybook, surfacing relevant information directly in Dev Mode's sidebar.
With Code Connect configured, the Figma MCP server outputs real design system code for AI code generation agents, bridging design tools and IDE workflows.
Figma originally used Skew, a custom statically-typed, object-oriented language created by co-founder Evan Wallace that compiled to JavaScript. It was eventually abandoned due to onboarding friction and migrated to TypeScript.
graph LR
subgraph Skew["Skew Language"]
SOUND["Sound Type System
(nominal typing)"]
WRAP["Wrapped Types
(zero-cost abstractions)"]
OPT["Compiler Optimizations
(devirtualization, inlining)"]
end
subgraph Migration["3-Phase Migration"]
TRANS["Custom
Transpiler"]
WASM2["WebAssembly
Adoption"]
end
subgraph Target["TypeScript + React"]
TS["TypeScript UI
Layer"]
CPP["C++ Engine
(via Wasm)"]
end
SOUND --> TRANS
WRAP --> TRANS
OPT --> TRANS
WASM2 --> TRANS
TRANS --> TS
TRANS --> CPP
style SOUND fill:#1a1a3e,stroke:#f43f5e,color:#f0f0f0
style WRAP fill:#1a1a3e,stroke:#f43f5e,color:#f0f0f0
style OPT fill:#1a1a3e,stroke:#f43f5e,color:#f0f0f0
style TRANS fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style WASM2 fill:#1a1a3e,stroke:#a855f7,color:#f0f0f0
style TS fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style CPP fill:#1a1a3e,stroke:#7c3aed,color:#f0f0f0
Despite its performance benefits from sound type system optimizations (devirtualization, constant folding, dead code elimination), Skew created significant onboarding friction for new engineers and lacked external ecosystem support. The migration to TypeScript became feasible because WebAssembly adoption meant the C++ engine replaced many core Skew components, reducing the performance cost of moving to TypeScript.
A summary of Figma's complete technology stack across all layers, including several technology migrations that reflect the platform's evolution over the past decade.
| Layer | Technology | Notes |
|---|---|---|
| Rendering engine | C++ → WebAssembly (Emscripten) | rendering |
| GPU API | WebGL 2.0 → WebGPU | rendering |
| Shading language | GLSL → WGSL | rendering |
| UI framework | Skew → TypeScript + React | language |
| Multiplayer server | TypeScript → Rust | collab |
| Serialization format | Kiwi (custom binary, like Protobuf) | collab |
| File storage | Amazon S3 | storage |
| Write-ahead log | Amazon DynamoDB | storage |
| Metadata database | Amazon RDS PostgreSQL (sharded) | infra |
| Real-time transport | WebSockets | collab |
| Plugin sandbox | Realms (main thread) + iframe (UI) | plugins |
| Design-to-code bridge | Code Connect (UI or CLI) | dev mode |
| Cloud provider | AWS | infra |
Figma's engineering decisions reveal a pattern of choosing unconventional approaches -- custom renderers, custom languages, custom serialization formats -- to achieve performance that would be impossible with off-the-shelf solutions.
graph TD
subgraph Chose["Figma Chose"]
A["Custom GPU
Renderer"]
B["C++ / Wasm
for Core"]
C["LWW over
Full OT"]
D["Realms Sandbox
over Workers"]
E["S3 + DynamoDB
over RDS"]
end
subgraph Gained["What They Gained"]
A1["Native-app
performance"]
B1["Low-level
GPU control"]
C1["Simpler conflict
resolution"]
D1["Sync document
access"]
E1["Cost-effective
file storage"]
end
subgraph Cost["What It Cost"]
A2["Build everything
from scratch"]
B2["Split-world
debugging"]
C2["Not ideal for
text collab"]
D2["Careful sandbox
security"]
E2["Multi-service
complexity"]
end
A --> A1
A --> A2
B --> B1
B --> B2
C --> C1
C --> C2
D --> D1
D --> D2
E --> E1
E --> E2
style A fill:#1a1a3e,stroke:#7c3aed,color:#f0f0f0
style B fill:#1a1a3e,stroke:#3b82f6,color:#f0f0f0
style C fill:#1a1a3e,stroke:#06b6d4,color:#f0f0f0
style D fill:#1a1a3e,stroke:#14b8a6,color:#f0f0f0
style E fill:#1a1a3e,stroke:#f97316,color:#f0f0f0
style A1 fill:#0a1a0a,stroke:#22c55e,color:#f0f0f0
style B1 fill:#0a1a0a,stroke:#22c55e,color:#f0f0f0
style C1 fill:#0a1a0a,stroke:#22c55e,color:#f0f0f0
style D1 fill:#0a1a0a,stroke:#22c55e,color:#f0f0f0
style E1 fill:#0a1a0a,stroke:#22c55e,color:#f0f0f0
style A2 fill:#1a0a0a,stroke:#ef4444,color:#f0f0f0
style B2 fill:#1a0a0a,stroke:#ef4444,color:#f0f0f0
style C2 fill:#1a0a0a,stroke:#ef4444,color:#f0f0f0
style D2 fill:#1a0a0a,stroke:#ef4444,color:#f0f0f0
style E2 fill:#1a0a0a,stroke:#ef4444,color:#f0f0f0
Each open document gets its own server process, providing clean isolation but requiring infrastructure to route all editors of a document to the same server process. This architectural choice simplifies concurrency but adds operational complexity for process routing and management.