Skip to content

SYSTEM Cited by 1 source

Yelp CHAOS

Definition

CHAOS is Yelp's internal server-driven UI (SDUI) framework. The server authors a CHAOS Configuration (a bundle of views, layouts, components, and actions) per request; the client (iOS, Android, web) reads the configuration and renders a UI that the server fully determined. CHAOS was first introduced publicly in Yelp's 2024-03 post and the backend was unpacked in "Exploring CHAOS: Building a Backend for Server-Driven UI" (2025-07-08).

Surface area

  • GraphQL API — a single CHAOS Subgraph in Yelp's Apollo Federation supergraph. Clients issue a chaosConfiguration(name, context) query.
  • CHAOS REST API — the contract each CHAOS backend service implements; the subgraph routes to the backend for the requested view. Multiple teams run their own CHAOS backend, all conforming to this contract.
  • Python Strawberry subgraph — the GraphQL-facing layer.

Build pipeline

Four layers, all named in the post:

  1. ChaosConfigBuilder — request entry point; holds registered ViewBuilder classes and returns the final configuration.
  2. ViewBuilder — one class per logical view (view_id() == e.g. consumer.welcome). Selects the layout and declares optional subsequent views for view flows.
  3. LayoutBuilder — e.g. SingleColumnLayoutBuilder (one main section) or mobile layouts with toolbar/footer sections. Holds an ordered list of FeatureProviders per section; order == render order.
  4. FeatureProvider — one per product feature; produces the components and actions that implement the feature. Follows the six-stage lifecycleregistersis_qualified_to_loadload_dataresolveis_qualified_to_presentresult_presenter.

The build runs FeatureProviders in two parallel loops: loop 1 fires all async upstream requests, loop 2 waits on results and composes components. ("The latest CHAOS backend framework introduces the next generation of builders using Python asyncio, which simplifies the interface" — a future post will cover this.)

Element model

Components and actions are JSON strings inside a stable GraphQL schema (concepts/json-string-parameters-for-schema-stability):

  • ChaosJsonComponent{ identifier, componentType, parameters } — e.g. componentType: "chaos.button.v1" with parameters: "{\"text\": \"Find local businesses\", ...}".
  • ChaosJsonAction{ identifier, actionType, parameters } — e.g. actionType: "chaos.open-subsequent-view.v1" with parameters: "{\"viewId\": \"consumer.view_two\"}".

Backend Python dataclasses (TextV1, ButtonV1, IllustrationV1, OpenUrlV1, OpenSubsequentView, ViewPlaceholderV1, …) type-check the element content before serialisation.

Client capability matching

A FeatureProvider.registers returns a list of Register entries, each carrying a Condition(platform=[...], library=[...]) and a presenter_handler. First matching condition wins; if no register matches the requesting client, the feature is omitted from the response. This is how Yelp keeps old app versions working while new components ship — see concepts/register-based-client-capability-matching.

Error isolation

Every FeatureProvider is wrapped in an error decorator (patterns/error-isolation-per-feature-wrapper). An exception in one feature drops that feature only; the rest of the view still renders. Developers can flag a provider as IS_ESSENTIAL_PROVIDER = True to opt out — if the feature is "essential," its failure fails the whole view.

Failure logs include feature name, owner, exception details, and request context — used for threshold-based alerting and owner-team notification.

Advanced primitives

  • View FlowsViewBuilder.subsequent_views() returns additional ViewBuilder classes whose output is packed into the same response's views array. Navigation happens locally via chaos.open-subsequent-view.v1 actions — no network round-trip. Canonical example: Yelp for Business customer-support FAQ menu. See patterns/preloaded-view-flow-for-predictable-navigation.
  • View PlaceholdersViewPlaceholderV1 embeds a nested CHAOS view that the client fetches asynchronously after rendering the parent. Configurable loading / error / empty / header / footer component IDs and an estimatedContentHeight for layout stability. Production example: Yelp for Business home screen embeds the Reminders feature (served by a different CHAOS backend) as a placeholder. See patterns/view-placeholder-async-embed.

Known tradeoffs

  • GraphQL schema stability bought at the cost of losing per-element schema validation in GraphQL introspection (payloads are opaque strings). Backend dataclasses and client-side renderers must agree out-of-band.
  • Register-based capability gating is first-match and order- sensitive; correctness depends on most-specific-first ordering.
  • Two-loop build pattern is a pre-asyncio design; an asyncio- native redesign is in flight.
  • No disclosed operational numbers (latency, RPS, cache hit rates) — the post is an architecture walkthrough, not a retrospective.

Seen in

Last updated · 476 distilled / 1,218 read