System Design Space
Knowledge graphSettings

Updated: June 22, 2026 at 5:40 AM

Frontend Data Layer: REST, GraphQL, BFF, and Orchestration

medium

How to design the frontend data layer: REST, GraphQL, BFF, route loaders, aggregation, partial failures, retries, and contract evolution.

The frontend data layer becomes an architectural topic as soon as a screen stops reading one API endpoint and starts assembling user experience from several services with different response speeds. At that point, the choice between REST, GraphQL, BFF, and route loaders directly affects UX.

The chapter is valuable because it treats data flow as architecture rather than a set of fetch calls. What matters is not only how data is loaded, but where aggregation happens, who owns retries, how stale or partial data is shown, and what contract remains between the interface and the server side.

For architecture reviews, this material helps discuss client data through ownership boundaries, orchestration, and failure handling instead of reducing everything to a protocol or request-library choice.

Practical value of this chapter

Design in practice

Split routes by data-loading style: where REST is enough, where GraphQL helps, and where a BFF should assemble the screen model.

Decision quality

Evaluate the data layer through contract predictability, partial-failure handling, retries, cache behavior, and aggregation cost.

Interview articulation

Structure answers as route class, data sources, aggregation point, error strategy, cache behavior, and contract ownership.

Trade-off framing

Make the cost explicit: client simplicity, query flexibility, server-facade control, operating complexity, and API change speed.

Context

REST, gRPC, and GraphQL

Transport choice is only useful as part of a larger discussion about UI-facing contracts, retries, and aggregation.

Читать обзор

The data layer determines whether a screen stays predictable when it has to assemble a response from several server-side services. If the interface handles partial failures and still needs to return a compact view model quickly, it needs an explicit architectural layer between the screen and transport details.

The network call is just the top layer. Below it sit UI-facing contracts, orchestration, retries, and stale states — and, with them, the question of who owns all this when a screen stops behaving as expected.

Frontend data layer map

One screen can call REST endpoints directly, go through GraphQL, receive a ready-made view model from a BFF, or combine several approaches. Switch modes to see where data is assembled and where the contract should live.

Data pathScreenBFFServicesView model

BFF as a server-side facade for the interface

The BFF assembles data on the server side and returns a ready view model to the screen.

1

Consumer

Screen

The interface needs a compact response without knowing internal service structure.

2
↓ requests

Facade

BFF

The layer handles authentication, localization, permissions, and product-specific scenarios.

3
↓ aggregates

Sources

Server services

Internal domains can remain independent instead of adapting directly to UI needs.

4
↓ simplifies

Output

View model

The screen receives a ready data shape, while aggregation complexity stays on the server.

When to choose

When to choose

  • The server side is fragmented.
  • Internal DTOs need to be hidden behind a screen-shaped model.
  • Contract control, security, and unified error handling matter.
A BFF reduces client complexity, but it becomes an important server layer of its own: observe it, version it, and keep it from expanding without boundaries.

Integration models

REST + route loaders

The cheapest start for predictable screens with clear boundaries. It holds while a screen needs only a handful of requests and the contract evolves without frequent breaking changes. Once requests pile up, orchestration drifts into the components and the simplicity advantage disappears.

GraphQL

Useful when the interface assembles data from multiple domains and the API shape changes often. The trade-off is schema governance, client-cache complexity, and protection against expensive queries.

BFF / UI orchestration layer

Useful when the server side is fragmented or the interface needs a compact view model shaped around authentication, localization, and product-specific aggregation.

Hybrid approach

In practice one product rarely lives on a single option: BFF for critical user flows, GraphQL for exploratory screens with flexible queries, and REST for stable operational screens. The price of that choice is several contracts you have to evolve in step.

Related

Customer-Friendly API

A strong frontend data layer almost always depends on an API shape that fits the product, not only the service infrastructure.

Open chapter

Rules for resilient data flow

Partial failure is part of the UX design

If one analytics widget is unavailable, the rest of the page should not necessarily collapse. The data layer should distinguish hard failure, stale fallback, and incomplete response.

Retry policy does not live only in transport

Retry behavior depends on user intent, idempotency, loading cost, and whether stale state can be shown safely instead of aggressively fetching again.

A view model beats raw service contracts

Interfaces benefit from API shapes that are close to the screen. Otherwise orchestration leaks into hooks, selectors, and component trees.

Data contracts should evolve like public APIs

BFFs, GraphQL schemas, and typed clients need a clear deprecation policy. Otherwise screen migration starts blocking the release cadence of multiple teams.

Questions before choosing BFF or GraphQL

  • How many server domains one screen must assemble and where API aggregation is cheapest.
  • Whether the interface needs a stable view model or individual service DTOs are already close enough to the screen.
  • How important partial response, request cancellation, optimistic update, and background refresh are for this route.
  • Who owns schema evolution: the frontend platform, a product team, or a backend team with a UI-facing contract.

Main anti-pattern

Leaving orchestration at the component level means one screen pulls dozens of hooks and knows more about server-domain internals than the platform team. The cost shows up not right away but on the first contract change — error handling scatters across components, and any migration turns into hand-editing dozens of places.

Related chapters

Enable tracking in Settings