Steven's Knowledge

BFF (Backend for Frontend)

When the API your services offer and the API your UI needs diverge — a dedicated backend per frontend, what it solves, and where it goes wrong

BFF (Backend for Frontend)

A BFF is a backend service whose only job is to serve one specific frontend — typically one client type (mobile app, web app, voice assistant, smart TV). Instead of all clients calling a single shared API, each client has its own backend tailored to its shape, data needs, and constraints.

The pattern was named at SoundCloud around 2012 and popularized by Sam Newman shortly after. Like most architectural patterns it solves a specific problem (mismatch between general APIs and client-specific needs) and creates new ones (more services to operate, careful boundaries to maintain). This page is about when the pattern earns its cost and when it adds ceremony without payoff.

The Problem BFF Solves

A typical "one API serves many clients" arrangement strains over time:

                    ┌──────────────────┐
   Mobile app ────▶ │                  │
   Web app ───────▶ │   Shared API     │ ───▶ Order Service
   Smart TV ──────▶ │   Gateway        │ ───▶ Catalog Service
   Voice device ──▶ │                  │ ───▶ Payments Service
                    └──────────────────┘

The mobile app wants fewer, denormalized responses to minimize round trips. The web app wants richer payloads with more nested data. The smart TV needs media-specific transformations. The voice device wants text-only responses.

A single shared API tries to satisfy all of them and ends up:

  • Over-fetching on some clients ("I asked for the order, got 200KB").
  • Under-fetching on others ("I need three API calls to render this screen").
  • API surface bloat: every client's needs accreted as parameters and query strings.
  • Slow evolution: changing the API requires considering every client, which blocks faster-moving clients on slower ones.

The BFF Pattern

Replace the single shared API with one BFF per frontend type:

                  ┌──────────────┐
   Mobile app ──▶ │ Mobile BFF   │ ──┐
                  └──────────────┘   │
                  ┌──────────────┐   │
   Web app ─────▶ │ Web BFF      │ ──┼──▶ Backend services
                  └──────────────┘   │    (Orders, Catalog,
                  ┌──────────────┐   │     Payments, ...)
   Smart TV ────▶ │ TV BFF       │ ──┘
                  └──────────────┘

Each BFF:

  • Serves exactly one frontend, owned by the same team that owns that frontend.
  • Aggregates multiple backend service calls into a single response shaped for the screen.
  • Transforms data into the format the client wants (date formats, image sizes, label texts).
  • Handles client-specific concerns: authentication for that channel, version negotiation, feature flags relevant to that client.
  • Has the same lifecycle as the frontend: ships when the frontend ships, deprecates when the frontend deprecates.

The backend services stay general; the BFF localizes the per-client adaptation.

What BFF Buys

The benefits are concrete:

  • Right-shaped responses. The mobile BFF returns exactly what the mobile screen needs; the web BFF returns exactly what the web screen needs. Neither over- nor under-fetches.
  • Independent evolution. The mobile team can change its BFF without web-team negotiation. Releases align with their own client.
  • Backend service stability. General backend services are not pulled into client-specific changes. They evolve based on domain needs, not UI needs.
  • Aggregation done server-side. Three backend calls combine into one BFF response, saving mobile bandwidth and reducing client complexity.
  • Channel-specific concerns localized. Mobile session handling, web cookies, TV remote-control input — each BFF handles its channel's quirks without polluting others.

What BFF Costs

The honest tradeoffs:

  • More services to operate. N frontends mean N more deployable services, each with its own pipeline, dashboards, alerts, on-call.
  • Duplication risk. Two BFFs both need user-formatting logic; if duplicated, they drift. Shared libraries help but introduce coupling.
  • Aggregation logic moved, not eliminated. The complexity of fetching from three backend services and combining them lives in the BFF instead of the client. It is somewhere; pick where it is least painful.
  • Coupling between frontend and BFF is total. Changing the screen often changes the BFF in the same PR. This is by design — frontend and BFF are essentially one unit — but it means BFF/frontend ownership must be one team.
  • Boundary creep. A BFF starts as a thin aggregation layer; over time it accumulates business logic. Without discipline, BFFs turn into a second domain layer competing with the backend services.

When BFF Is the Right Answer

The signals that justify the cost:

  • Multiple distinct frontends with different shapes. Mobile + web + smart TV is the canonical case. Two web apps with similar shapes is borderline.
  • Independent client teams. The mobile team is separate from the web team is separate from the TV team. BFF aligns architectural and team boundaries (see Conway's Law).
  • Backend API does not naturally match UI shape. The general API gives raw domain data; screens need composed, formatted, conditionally-shaped responses.
  • Aggregation latency matters. Three backend calls from a mobile device over LTE is much worse than one BFF call. The aggregation belongs server-side.

When BFF Is the Wrong Answer

  • One frontend, one backend. Just call the backend. BFF adds a hop without solving anything.
  • Backend services already shape responses per client. If your backend services maintain different endpoints per client, you have BFF-style functionality inside the wrong layer. Better to extract them, but it is more refactoring than greenfield.
  • Aggregation could be done by an API Gateway. If your needs are routing, rate-limiting, auth, and lightweight transformation, an API Gateway is lighter than a BFF. BFFs are for non-trivial composition; gateways are for cross-cutting concerns.
  • Small team that cannot afford multiple services. Splitting the same team across N BFFs is not autonomy; it is dilution.

BFF vs API Gateway

These are related but different patterns:

AspectBFFAPI Gateway
NumberOne per frontend typeTypically one for the whole system
OwnerThe frontend teamA platform team
LogicClient-specific aggregation, transformation, compositionCross-cutting: auth, rate-limit, routing, observability
Coupling to clientTight (same team, same release)Loose (clients are independent of gateway)
ReplacesSome calls to backend servicesThe need for clients to know about service topology

A mature system often has both: an API Gateway in front of backend services for cross-cutting concerns, plus BFFs for client-specific composition. They are not in competition.

Failure Modes

The Distributed Monolith BFF

A single BFF that serves all frontends, sharing logic in a single deployable. This is not BFF — it is one shared API again, with extra steps. The pattern requires one BFF per frontend type with separate ownership and lifecycle.

Shared Libraries Pulling BFFs Together

Three BFFs all import a shared utility library for user formatting. The library accumulates client-specific logic. Eventually every change to the library affects all BFFs, defeating the independence the pattern was supposed to provide. Keep shared libraries small and stable; let BFFs duplicate genuinely client-specific code.

BFF Becomes a Second Domain Layer

Business rules creep into the BFF — order validation, pricing calculations, inventory checks. Now you have two domain models: the backend services' and the BFF's. They will drift. Keep business rules in backend services; BFFs aggregate and transform.

BFF as a Gateway

Putting cross-cutting concerns (auth, rate-limiting, request logging) into BFFs instead of an API Gateway. Each BFF reimplements them slightly differently. Now operational quality varies per client. Use a gateway for cross-cutting; use BFFs for composition.

Wrong Team Ownership

A platform team owns the BFFs. Frontend teams have to coordinate every BFF change with the platform team. This eliminates the autonomy that BFFs exist to provide. BFFs belong to the frontend team or they are not BFFs.

A Worked Example

A media-streaming service with mobile, web, and TV apps:

Mobile BFF (/mobile/v3/home):

  • Returns a compact JSON: list of 10 cards, each with a small thumbnail URL, title, and play_url.
  • Authenticates via mobile OAuth flow.
  • Returns 304 aggressively for unchanged feeds.

Web BFF (/web/api/home):

  • Returns a richer JSON: list of 30 cards, each with multiple image sizes, description, cast list, related content.
  • Authenticates via cookie session.
  • Includes HTML-ready text snippets.

TV BFF (/tv/v1/home):

  • Returns TV-optimized: rows of media organized for remote-control navigation, large image URLs, focus hints.
  • Authenticates via paired device flow.
  • Includes accessibility annotations.

All three call the same backend services — Catalog Service, Recommendations Service, User Profile Service — but compose and format differently. The Catalog Service does not change for any of them.

Common Mistakes

  • Treating BFF as a free lunch. BFFs solve aggregation/shape problems and introduce operational and coupling problems. Net positive only if the original problem was real.
  • Adding a BFF before you need one. A single frontend does not need a BFF; just call backend services directly. Add a BFF when the second frontend arrives with different needs.
  • BFF without team alignment. If the BFF is owned by a separate team from the frontend, the coupling becomes coordination tax. The team must be the same.
  • Skipping the gateway. Putting cross-cutting concerns into BFFs creates inconsistency. Use a gateway for cross-cutting, BFFs for composition.
  • Ignoring duplication. Three BFFs evolving independently start to drift in shared concerns. Either accept the duplication or pull shared logic into a stable library; do not pretend the problem will not arise.

Relation to Other Pages

  • Microservices — BFF is a microservices-adjacent pattern; the backend services it composes are typically microservices.
  • Modular Monolith — a modular monolith can serve multiple BFFs as its public interface.
  • Conway's Law — BFFs only work when frontend team and BFF ownership coincide.
  • Anticorruption Layer — a BFF can act as an ACL between an external API shape and a client's needs.

Further Reading

  • Phil Calçado, Pattern: Backends For Frontends (2015) — the foundational write-up that names and crystallizes the pattern.
  • Sam Newman, Pattern: Backends For Frontends — the article on samnewman.io, plus chapter treatment in Building Microservices (2nd ed., 2021).
  • Lukasz Plotnicki & Soundcloud Engineering — the originating engineering case study.
  • Stewart Gleadow, Why we leverage multi-tiered storage at Netflix — Netflix's adoption of a similar pattern at scale.

Pre-commit Checklist

  • For each frontend in my system, do I have a BFF, or is one shared API serving all of them — and if so, is the mismatch costing more than the BFF would?
  • Is each BFF owned by the same team as its frontend? If not, the autonomy benefit will not materialize.
  • Are cross-cutting concerns (auth, rate-limit, observability) in a gateway, not duplicated in each BFF?
  • Have I prevented business logic from migrating into BFFs? The domain belongs in backend services.
  • For shared concerns across BFFs, do I have a stable library — or are the BFFs drifting?
  • Have I justified the BFF cost with a concrete client-shape mismatch, not just "this is the modern pattern"?

On this page