intermediate 3 min answer

A product runs on web, iOS, Android and a television app. The shared API team is the bottleneck for every client change. Design the fix.

bffapi-designnetflixownershipconways-law
Show the full answer Hide the answer

What is being tested

Whether you recognise that this is an ownership problem expressed as an API problem, and whether your fix addresses the ownership.

The diagnosis

The bottleneck is not technical. Four client teams need changes in one component owned by a fifth team, so every client change is a cross-team negotiation with queueing. Conway's Law is operating exactly as advertised: the communication structure has become the delivery constraint.

There is a technical symptom on top of it. A shared general-purpose API is optimised for nobody: the television app receives fields it never renders, the phone client makes three round trips to build one screen because the endpoint shapes do not match its layout, and every client is served the union of everyone's needs over whatever network they happen to be on.

The fix: a backend for frontend per client class

Each client team owns a thin backend that aggregates from downstream services and returns exactly what its client renders.

The load-bearing detail is ownership. A BFF owned by a central platform team is just the same API with an extra hop and the same queue. The pattern only pays off when the team that needs the change can make it without asking anyone. This is what Netflix's move to client-specific backends was actually buying: a very large number of device types with different capabilities, memory limits and network conditions, and no way for a single API team to serve them all without becoming the constraint on every one.

Design rules

  • Per client class, not per screen. Four BFFs, not forty. Proliferation multiplies deployables for no benefit.
  • Keep them thin. Aggregation, shaping and client-specific concerns only. Business rules stay in the services that own them — a rule duplicated across three BFFs will drift, and if it is an authorisation rule the drift is a security incident.
  • Fan out in parallel, with a per-call timeout and an overall screen budget. A BFF aggregates the latency tails of every service it calls, so without budgets the slowest dependency defines the user experience.
  • Degrade partially. If recommendations fail, render the screen without that shelf rather than failing the response. This is where the pattern adds genuine product value, and it is only possible because the BFF knows what the screen needs.
  • Accept duplication between BFFs. Two BFFs solving similar problems differently is the intended outcome. Factoring out their commonality recreates the shared API you were escaping.

What must not be duplicated

Authentication and coarse authorisation belong at the edge or in the services, not reimplemented per BFF. Domain invariants belong in the owning services. If a rule matters for correctness, one place owns it.

When a shared API is the better answer

With one client, or with several clients whose needs genuinely coincide, a well-designed shared API is simpler and cheaper. The pattern is a response to divergence and to ownership friction; without either, it is four deployables where one would do.

A middle option worth considering before committing: a query language that lets each client request exactly the fields it needs from one endpoint. It addresses the payload problem well and the ownership problem not at all — so if the bottleneck is the team queue rather than the payload size, it will not fix what is actually wrong.