Backends for Frontends
Context
Section titled “Context”You introduced an API Gateway and it worked. But your clients are not the same. The web app runs on a fast connection and wants rich, detailed responses to render a wide dashboard. The mobile app runs on a flaky cellular link and wants small, compact responses with only the fields the small screen shows. A third-party integration wants stable, conservative, versioned endpoints that rarely change. A single gateway trying to satisfy all three keeps growing conditional logic and “include this field only for mobile” special cases.
Problem
Section titled “Problem”One gateway shared by every client type becomes a contested, ever-growing component. Every client team must coordinate its changes through that one shared codebase, so the mobile team waits on the web team and vice versa. The API drifts toward a lowest-common-denominator shape that fits no client well — too heavy for mobile, too thin for web. And ownership is muddy: who owns the gateway when three teams depend on it? How do you keep the benefits of a single entry point while letting each client evolve its own API at its own pace?
Solution
Section titled “Solution”Backends for Frontends (BFF) applies the gateway pattern once per client type. Instead of one gateway, you run a separate gateway for each kind of client — a web BFF, a mobile BFF, a third-party BFF. Each BFF exposes an API shaped precisely for its client: the mobile BFF returns trimmed payloads, the web BFF returns rich aggregates, the third-party BFF exposes a stable, slowly-versioned contract.
The decisive change is ownership. Each BFF is owned by the team that builds that client. The mobile team owns the mobile BFF and ships changes to the client and its backend together, with no cross-team coordination. The shared internal services stay untouched behind all the BFFs.
flowchart LR Web[Web App] --> WBFF[Web BFF] Mobile[Mobile App] --> MBFF[Mobile BFF] Third[Third-party client] --> TBFF[Third-party BFF] WBFF --> O[Order Service] WBFF --> C[Customer Service] MBFF --> O MBFF --> I[Inventory Service] TBFF --> O TBFF --> C
Example
Section titled “Example”Each BFF is its own deployable with its own configuration, tuned to its client. Here are two BFF route configurations over the same internal services — note how the mobile BFF trims fields and tightens limits while the web BFF returns rich aggregates.
# mobile-bff.yaml — small payloads, conservative limits for cellular clientslisten: ":443"routes: - path: /m/order/:id aggregate: - get: http://order-service/orders/:id as: order - get: http://inventory-service/stock/:sku as: stock response_shape: fields: [order.id, order.status, order.total, stock.available] # trimmed rate_limit: requests_per_minute: 60---# web-bff.yaml — rich aggregates for a fast connection and a wide screenlisten: ":443"routes: - path: /w/order/:id aggregate: - get: http://order-service/orders/:id as: order - get: http://customer-service/customers/:customerId as: customer - get: http://inventory-service/stock/:sku as: stock response_shape: fields: [order, customer, stock] # full objects rate_limit: requests_per_minute: 240Resulting context
Section titled “Resulting context”What you gain:
- Tailored APIs. Each client gets responses shaped exactly for its screen, network, and needs — small for mobile, rich for web, stable for third parties — with no compromise to fit the others.
- Clear ownership and autonomy. Each client team owns its BFF and ships client and backend changes together, removing the cross-team coordination that a shared gateway forces.
- Smaller blast radius. A change or bug in the mobile BFF cannot break the web client, because they are separate deployables.
What it costs you:
- Some duplication. Routing rules, authentication wiring, and aggregation logic recur across BFFs. Common concerns can be factored into a shared library, but you accept more moving parts than a single gateway has.
- More components to operate. Several BFFs mean several things to deploy, monitor, and keep available, instead of one.
- A boundary to police. Each BFF must stay a thin tailoring layer. If client-specific BFFs start absorbing business logic, you re-create the God-object problem the pattern was meant to solve — just spread across several places.
Related patterns
Section titled “Related patterns”- API Gateway — the single-gateway pattern that BFF specialises per client type.
- Service Discovery — how each BFF locates the internal services it calls.
- API Composition — the aggregation each BFF performs to compose a client-shaped response.