Skip to content

PATTERN Cited by 1 source

Runtime orchestration toward unidirectional flow

A client runtime that has grown by accretion — layout engines, variable resolvers, constraint enforcers, instance resolvers, rendering pipelines, each evolved independently, each scheduling itself in ad hoc ways — produces two diseases:

  1. Back-dirties (concepts/back-dirty) — later systems invalidate earlier systems' work, forcing re-runs, potentially oscillating.
  2. Unclear ownership and blurred responsibilities — "systems fight over the same subtree" because none of them can assume its inputs are stable.

The runtime orchestration toward unidirectional flow pattern is the fix:

  1. Introduce a shared orchestration layer that owns when each subsystem runs.
  2. Run subsystems in a predictable order, topologically sorted by their inter-subsystem dependencies.
  3. Use the predictable order as a detection substrate for back-dirties that were previously noise.
  4. Eliminate back-dirties by refactoring subsystem responsibilities (push deps upstream, demote competing writers, separate compute-from-write phases).
  5. Converge toward unidirectional flow: source-of-truth changes → subsystem₁ → subsystem₂ → … → rendered output, never backward.

Canonical source: sources/2026-04-21-figma-rebuilt-foundations-of-component-instances:

"We improved how our various runtime systems work together by unifying them under a common framework. The new approach has better separation of concerns (systems no longer need branching logic that special-cases instances), and the data flow is now one-directional which improves predictability of side effects."

The two-step pattern

Step 1: unification. Subsystems stop scheduling themselves independently. The orchestration layer has a schedule (usually per edit / per tick / per frame) and calls each subsystem in order. Each subsystem exposes compute() and apply() methods; the orchestrator decides when.

Step 2: cleanup via visibility. Predictable execution order makes order-of-magnitude more back-dirties visible — if after ordering subsystem i before j, j's output still requires a second pass of i, there's an edge from j back to i that shouldn't exist. These were invisible under ad hoc scheduling (just noise in the perf trace); now they're discrete signals a team can enumerate and kill one by one.

Prerequisites

  • Shared reactivity substrate. Figma picked push-based invalidation with automatic dependency tracking. A unified reactivity model is usually prerequisite — subsystems need to speak the same dirty / recompute language.
  • Clear subsystem boundaries. If responsibilities are interleaved (instance resolution doing layout; layout doing variable evaluation), unification is blocked until the separation of concerns cleanup happens. Figma's post describes exactly this cleanup as part of the Materializer project.
  • Willingness to break existing perf profiles. Porting each subsystem into the shared orchestration introduces "subtle differences in execution order and behavior." Figma absorbed this risk with side-by-side validation for months before rollout.

Why unidirectional flow is the correctness property

A fully unidirectional client runtime is a DAG: every subsystem S has a strict set of upstream subsystems it reads from and downstream subsystems it writes to, with no cycles. Given such a DAG, one pass through the topological order is guaranteed to produce a fixed point — no back-and-forth, no re-runs, no oscillation. The framework's scheduling becomes trivial (just walk the DAG); the only remaining work is per-node reactivity (which nodes in each subsystem to recompute, handled by push-based invalidation).

Figma frames this as "more closer to" unidirectional — an asymptote, not a claim of full achievement. The real-world practice is to kill back-dirties one at a time and monitor for new ones as the runtime grows.

  • Redux / Flux — unidirectional data flow was the central design commitment. Same idea, applied to app state.
  • Game engine ECS systems — per-frame subsystem scheduling in a strict order; classic unidirectional runtime.
  • Spreadsheet recalc — cells form a DAG; one topological sweep per change.
  • CI pipelines — stage graph is a DAG; no backward edges by construction.
  • Kubernetes controller chains — level-triggered reconciles on idempotent writes; not fully unidirectional but structurally similar.

Figma's contribution is applying this discipline at the client runtime layer of a collaborative design editor, where historically subsystems had been written by independent teams without a shared orchestration contract.

Cost

  • Migration effort. Years of subsystem evolution must be refactored into the new orchestration framework.
  • Ongoing tax. New subsystems must fit the orchestration — no more "run whenever I notice I have work." Teams that want the velocity of the old model must be disciplined.
  • Rollout risk. Order-of-execution changes produce subtle behavior differences in edge cases unit tests don't cover. The side-by-side runtime validation pattern is the de-risking mechanism.

Seen in

Last updated · 200 distilled / 1,178 read