A Tale of Two Parameter Architectures — and How We Unified Them¶
Summary¶
Figma retrospective on unifying the architectures behind its two
parameter systems — component properties (launched 2022,
scoped parametrization: parameters defined on a component, bind to
layers inside that component) and variables (launched 2023, global
parametrization: parameters defined at the library level, bind to
layers in any file with access). Both systems are instances of
"set-once, apply-across" parametrization (change the parameter value
→ all bound layer properties update) but evolved independently with
parallel type definitions and parallel binding-storage, leading by
2024 to: user-visible inconsistencies (same layer property bound to
both a variable and a component property → inconsistent render), a
doubled implementation cost for each new type, inability to bind
cross-system (no number component property → can't bind to a
number variable), and a blocker for a third prospective parameter
system (upcoming Figma Sites CMS). The fix consolidates the two at
the data-model level (single typespace + single binding store)
and at the runtime level (one tracking/invalidation/resolution/
update flow), so any future parameter system inherits both.
Key takeaways¶
-
Parallel type definitions across sibling systems are a one-way ratchet of accidental complexity. Before unification,
VariableType.BOOLEANandComponentPropType.BOOLEANwere distinct types maintained separately. Adding a new type required implementing it twice. Worse, cross-system bindings were impossible: you couldn't bind a component property to anumbervariable becausenumbercomponent properties "simply just didn't exist within the system's vocabulary." Consolidating into a single typespace was the key enabler for the component-property-to- variable binding feature. -
Binding storage should be shared, and one layer property should bind to at most one parameter. Each parameter system originally stored its own bindings on layers, which let a layer bind the same property to a variable and a component property simultaneously — producing an unclear source of truth and inconsistent rendering. Unification collapses to a single binding store with the invariant "at most one parameter per bound property." Any future system inherits this contract without building its own binding infrastructure.
-
Source-of-truth location is orthogonal to data-model unification. Component properties live on a component/instance layer; variables live at the library level. This difference is preserved — unification happened around the typespace and the binding storage, not the source-of-truth residence. The takeaway generalizes: "where the parameter lives" and "what shape the parameter has" are separable axes; consolidate the shape, keep the residence flexible.
-
Parameter-system runtime decomposes into four stages, all of which were duplicated before unification. (1) Parameter usage tracking (what layer properties are bound to each parameter, tracked at property granularity). (2) Invalidation (when a parameter changes or a binding changes or a variable mode switches, find every affected property across every layer). (3) Resolution (re-resolve each affected property's value — possibly traversing multi-hop chains like variable aliases or cross-system binds). (4) Updates (re-render layers with resolved values). Before unification each parameter system had its own four-stage pipeline; after, all systems share one.
-
Transitive resolution is the load-bearing resolution primitive. A variable can alias another variable (brand-primary → blue-500);
button-primary-bg → brand-primary → blue-500must walk the whole chain. The unified typespace is what makes the walk typechecked end-to-end, including across parameter-system boundaries (component property → variable → aliased variable). -
Granularity of invalidation is tunable and shipped as a win. Unification let Figma tighten invalidation from layer-level to property-level. "Substantially reduced the total time it takes to add, delete, and duplicate variable modes, as well as change variable values" — no numbers, but a named perf outcome from stricter granularity alone.
-
The unified architecture is a platform bet, not a one-off cleanup. Explicit motivation: a prospective third parameter system (Figma Sites CMS, announced at Config) gets the runtime for free. Figma Sites and Figma Buzz both intend to lean more on parametrization going forward. The retrospective's framing is that separate architectures "made it nearly impossible to bring parametrization to other Figma products without inheriting these technical burdens" — i.e. the duplication wasn't just a cost, it was a capability ceiling.
Architectural numbers / shape¶
- Two unified parameter systems today: component properties (scoped / on-layer) and variables (global / library-level).
- One prospective third: Figma Sites CMS.
- Unification dimensions: data model (typespace + binding-storage), runtime (tracking / invalidation / resolution / updates).
- Resolution fan-out: single hop (direct bind), multi-hop same-system (variable alias), multi-hop cross-system (component property → variable → alias).
- Invalidation granularity: layer-level (before) → property-level (after).
Caveats¶
- No latency / memory / throughput numbers; all results are qualitative ("substantially reduced").
- No mention of migration strategy for existing documents with multi-parameter-bound properties (the exact inconsistency class the unification removes).
- The runtime stages are described abstractly; no sizing / fan-out / algorithm detail (graph walk order, cycle detection, resolution scheduling).
- Blog post is a retrospective / success narrative from the team that did the work; treat claims of "significantly improved" accordingly.
Relationship to prior Figma wiki pages¶
This post sits cleanly above the QueryGraph substrate. Both are client-side reactive-graph designs over the object-tree data model, differing in what they index:
- QueryGraph indexes read+write dependencies between document nodes — foreign-key edges (instance → component) and implicit edges (auto layout, constraints). Powers subscription / dynamic-loading / collaborator edit fan-out.
- Parameter runtime indexes parameter-to-bound-property edges — which layer properties read from which parameter. Powers reactive re-resolution when parameter values change.
They share the "bidirectional in-memory index over document nodes" shape but serve distinct purposes and almost certainly run as separate data structures.
Original article¶
- Blog: https://www.figma.com/blog/a-tale-of-two-parameter-architectures/
- Raw file:
raw/figma/2026-04-21-a-tale-of-two-parameter-architectures-and-how-we-unified-the-caae7e30.md