Skip to content

ZALANDO 2021-03-10

Read original ↗

Zalando — Micro Frontends: from Fragments to Renderers (Part 1)

Summary

Jeremy Chone and co-authors describe Zalando's second micro-frontend generation: the move from Fragment-based Project Mosaic (2015) to the entity-based Interface Framework (IF; designed 2018, in production as of writing). By March 2021, ~90% of zalando.com traffic is served via Interface Framework. The post is Part 1 of a promised series; it lays out IF's feature set and architecture at a high level, and explicitly defers most internals to later posts.

The architectural thesis is an inversion. Mosaic composed pages from Fragments — each a team-owned frontend + backend pair that rendered its own slot. By 2018 this produced four recurring pains: tech-stack divergence, a high contribution barrier (teams built and operated whole Fragments), no centralised UX guarantees, and duplicated cross-cutting concerns (monitoring, A/B testing, consent, tracking). IF keeps feature-team ownership but reframes the composition primitive: pages are trees of typed Entities (Product, Collection, Outfit) picked per-request by personalisation, and Renderers — self-contained React components owned by feature teams — visualise one Entity type each. A central Rendering Engine (Node.js + browser runtime) walks the Entity tree, applies declarative rendering rules, and produces the Renderer tree. The GraphQL layer is the central data aggregator; each Renderer declares its data dependencies there. Cross-cutting concerns move into the platform: integrated monitoring, orchestrated A/B testing (batched to keep experiment latency overhead low), preview deployments that use production endpoints with 100% production routing, a unified design system with centralised component versioning and bundle-size optimisation, and performance quality gates (Lighthouse CI, Bundle Size Limits, Web Vitals). The organisational payoff: one monolithic repository for all feature teams on an aligned React + TypeScript + GraphQL stack; ownership blurred at the Renderer grain with explicit contribution guidelines; reliability improvements propagate site-wide.

Key takeaways

  1. The Fragment critique is Zalando's own, not a straw-man. The post names four structural pain points from Mosaic-in-production (2015–2018): stack divergence, high entry barrier per feature, no centralised UX/a11y guarantees, and duplicated cross-cutting concerns (Source: this post). That critique is the most load-bearing list in the wiki's Micro-frontends entry.
  2. Entities are the pivot. Zalando identified a "reasonably small" canonical set of content pieces (Product, Collection, Outfit) used across the core user journey. Entities serve both as the inter-service exchange vocabulary and as the node type for page layouts — same type, two roles. See concepts/entity-based-page-composition (Source: this post).
  3. Renderer is the contribution unit. Each Renderer is a self-contained, reusable React component visualising one Entity type; the mapping is one-to-many on the Entity side (an Outfit → main view or card in a collection) and one-to-one on the Renderer side (one Entity type per Renderer). See patterns/entity-to-renderer-mapping.
  4. Rendering rules are declarative. The mapping from Entity tree to Renderer tree is a declarative rule-set applied at request time by the Rendering Engine. The post does not disclose the rule language — promised for later posts.
  5. The Rendering Engine runs in Node.js and the browser. One code path, two execution environments — a universal rendering shape. SSR vs CSR vs streaming SSR boundary is not disclosed.
  6. Hybrid rendering modes are the migration load-bearer. A single view can be a pure Mosaic template, a mix of Mosaic fragments + Renderers, or pure Renderers — in one Rendering Engine. That is the mechanism that lets Mosaic and IF coexist as 90% of traffic moves to IF (Source: this post).
  7. Cross-cutting concerns move into the platform. IF centralises: monitoring, consent, A/B testing (with batched calls to Zalando's Octopus platform for low per-Renderer latency overhead), design system versioning, client-bundle-size optimisation, and production-routing preview deploys. Feature teams do not rewire these per Renderer — the third explicit Mosaic pain fixed.
  8. Performance quality gates are first-class. Lighthouse CI and Bundle Size Limits are per-PR CI gates; Web Vitals and custom metrics are always-on client telemetry. See patterns/page-performance-quality-gates (Source: this post).
  9. Organisational effect: shared monolithic repo, blurred Renderer ownership. Teams work in a single repo with a unified stack; multiple teams contribute to most Renderers under shared contribution guidelines. Described as a "cultural shift" away from Fragment-team-owns-its-slot.

Systems extracted

Concepts extracted

  • concepts/micro-frontends — new canonical concept page; Zalando's post is the clearest retrospective articulation of Fragment-based micro-frontend pain points on this wiki.
  • concepts/entity-based-page-composition — new concept; the architectural pivot Zalando makes from Fragments to Entities.
  • concepts/monorepo — IF consolidates into a single monorepo; adds the per-feature-team Renderer grain inside a monorepo altitude to the concept's Seen-in list.
  • concepts/universal-rendering — the Rendering Engine's Node.js + browser footprint.
  • concepts/conways-law — Mosaic's pain points are all Conway-shaped: Fragment boundaries became team boundaries, which became UX boundaries.

Patterns extracted

Operational numbers

  • ~90% of traffic served via Interface Framework as of March 2021.
  • Design started 2018. Three-year production ramp.
  • Mosaic introduced 2015. Coexists via three hybrid rendering modes.
  • Aligned stack: React, TypeScript, GraphQL, Node.js.

Caveats

  • Genre is architectural overview + advocacy, not production deep-dive. Part 1 of a promised series. No latency numbers, no QPS, no p99s, no cache-hit rates, no outage post-mortems, no Renderer count, no Entity type count, no bundle-size specifics.
  • Rendering rules DSL is not described. Named as "declarative set of layout rules" but its grammar, scoping, extensibility, and conflict-resolution rules are all deferred.
  • Rendering Engine internals are a black box. The post names it but does not disclose: streaming SSR vs classic SSR, caching, failure isolation across Renderers, concurrency model, or the request hot path.
  • Migration economics are not quantified. "We serve around 90% of traffic via Interface Framework." The cost of rewriting Mosaic Fragments into Renderers — team-years, incidents during migration — is not disclosed.
  • No disclosure of contributor count. Unlike the companion GraphQL post's "200+ developers across 25-30 feature teams," this post does not state how many teams contribute to IF.
  • Preview deploy gap detail missing. Preview deploys use "100% production routing" for authenticated developers, but the isolation story — how a broken preview is prevented from mutating production state — is not described.
  • Performance gate policies are not disclosed. Lighthouse thresholds, bundle-size budgets, and the list of custom client metrics are not enumerated.
  • The post is Part 1. Everything load-bearing — the rule DSL, the engine internals, the migration playbook, the observability story — is explicitly deferred to later posts.

Source

Last updated · 476 distilled / 1,218 read