Skip to content

SYSTEM Cited by 2 sources

Zalando Unified Backend-For-Frontends (UBFF) GraphQL

What it is

Zalando's single-service unified GraphQL schema that acts as the Unified Backend-For-Frontends for every Web and mobile-App feature team across Europe's largest fashion e-commerce platform. Development began in H1 2018; it has been in production since end of 2018. By February 2021 it spans 12+ domains in a shared-ownership monorepo, serves >80% of Web and >50% of App use cases, and is consumed by 200+ developers across 25-30 feature teams (Source: sources/2021-03-03-zalando-how-we-use-graphql-at-europes-largest-fashion-e-commerce-company).

Architectural shape

    Web clients        iOS/Android App clients
         │                      │
         ▼                      ▼
   ┌──────────────┐        ┌──────────────┐
   │ UBFF GraphQL │        │ UBFF GraphQL │
   │ (Web deploy) │        │ (App deploy) │  ← per-platform
   └──────┬───────┘        └──────┬───────┘     bulkhead
          │                       │
          └──────────┬────────────┘
       presentation-layer backends
       (domain + platform-specific logic)
              domain backends
              (Product, Campaign, …)

Two deployment shapes of the same codebase — one serving Web, one serving mobile Apps — implement the Bulkhead pattern. Behind the UBFF sits a presentation layer of domain/platform- specific backend services; the UBFF itself follows a strict No Business Logic principle and only aggregates and shapes.

Core design choices

  • One graph, one service. Unlike Apollo Federation, there is no runtime composition of subgraphs. One GraphQL service, one schema, one deployment artifact (two deployment shapes for platform bulkheading). The post is explicit: "instead of having multiple Graphs connected via a library and gateway we have a single service at Zalando which connects all the domains in a single schema Graph."
  • Entity system as first-class abstraction. Content and domain models are exposed as named entities — Product, Campaign, … — that cross-link into "a dense graph." The entity model is the schema's organising principle; the post flags it as the subject of its own future article (not detailed here).
  • JIT-compiled execution. Runs on graphql-jit — an open-source JIT GraphQL executor Zalando built and released as zalando-incubator/graphql-jit.
  • Shared-ownership monorepo. One repository owned by 12+ domain teams under a documented contribution framework; contributor count grew 50 → 150+ in 2020.
  • No business logic in the GraphQL layer. Enforced principle; domain/platform logic moves to presentation- layer backends behind the graph.

How they handle the "god component" risk

The post names the risk explicitly: a 12+ domain monorepo is a God Component architectural smell. Two mitigations:

  1. Architectural — shared ownership with an explicit contribution framework prevents any one team from unilaterally reshaping the graph.
  2. Operational — reliability patterns (Circuit Breakers, Timeouts, Retry) plus the Bulkhead pattern deployed as "separate deployments for Web and mobile Apps" — a Web regression cannot take the mobile app down and vice versa.

Adoption programme

Four levers the platform team used to scale adoption 50 → 150+ contributors and 70 → 200 consumers in 2020:

  1. One-stop-shop Documentation — single structured docs site (following Divio's documentation framework) with embedded GraphQL editor, schema documentation, Voyager for schema exploration, and practice exercises.
  2. Support chat — a dedicated channel for user and contributor queries.
  3. Trainings — company-wide GraphQL adoption training with 150+ participants.
  4. Consultation — platform team provides schema-design consultation hours for new domains ("GraphQL schema design is always a tricky topic even for frontend developers who can use GraphQL").

Positioning against peers

The post names and classifies five peer one-graph setups:

Org Shape Note
Zalando (this) Single service, unified schema Chosen: unified tooling, single deployment, single governance point
GitHub Single GraphQL API Covers repos, users, marketplace
Shopify Two unified graphs (StoreFront + Admin) Split by audience (customers vs partners)
Airbnb Working towards unified schema Presented at GraphQL Summit 2019
Expedia REST → GraphQL central data graph Motivated by "developers spending more time figuring out which service to call than shipping features"
Apollo Federation Library + gateway across N subgraphs Explicit not-chosen alternative
Netflix One-graph in Studio ecosystem Named peer

Operational numbers (2021-02 snapshot)

Dimension Value
First production deploy End of 2018
Domains in the graph 12+
Contributors to monorepo 150+ (from 50 in 2020)
Consuming developers 200+ (from 70 in 2020)
Feature teams served 25-30
Web use cases served >80%
App use cases served >50%
Platform-specific deployments 2 (Web + App)
Adoption training attendance 150+

Gaps in the public record

  • Schema size (type / field / resolver count) — undisclosed.
  • Latency SLOs, QPS, p99 — undisclosed.
  • Resolver fan-out / depth limits — undisclosed.
  • graphql-jit performance delta vs reference executor — undisclosed.
  • Entity system internals — deferred to future post.
  • Presentation-layer backend topology — described as "the presentation layer" with no further detail on per-domain or per-platform service topology.
  • Schema evolution / deprecation tooling — undisclosed.

Error modeling discipline (2021-04 follow-up)

A companion post, Modeling Errors in GraphQL (2021-04-12), establishes the UBFF's discipline for error payloads. The core rule is a two-channel split by who can act on the failure — see concepts/error-action-taker-classification:

The UBFF team is explicit that overusing schema Problem types — making every field a Success | Error union — destroys GraphQL's query-shape ergonomics, so Problem types are restricted to mutation inputs (Source: sources/2021-04-12-zalando-modeling-errors-in-graphql).

Seen in

Last updated · 476 distilled / 1,218 read