50%

الدرس 1 من 2

Why a Shared API Fails Several Clients

A single general-purpose API serving a web app, a mobile app and a partner integration ends up serving none of them well. A BFF is a per-experience answer.

قراءة 11 دقيقة

Once a system is several services, a client needs somewhere to talk to. The natural first answer is one API for everyone. It works while there is one client. It comes under pressure as soon as there are two with genuinely different needs, and the pressure is structural rather than a failure of API design.

ClientWantsSuffers from a shared API
Mobile appFew round trips, small payloads, aggressive aggregationOver-fetching on a metered network; six calls to render one screen
Web appRich data, rapid iteration alongside the frontendWaiting on an API team's release cycle for a field
Partner integrationStability, versioning, formal deprecationBreaking changes driven by internal client needs
Three clients, three sets of requirements that a single API must average across.

Shared API versus a backend per experience

The BFFs are thin. All the business logic remains in the services behind them.

On the left, three clients all call one shared API which calls four services. On the right, each client calls its own backend for frontend, and each of those calls whichever of the four services it needs. The partner integration keeps a formally versioned API of its own.

Clients

Mobile app

Web app

Partner systems

Per-experience backends

Mobile BFF

owned by the mobile team

Web BFF

owned by the web team

Public API

versioned, conservative

Domain services

Catalogue

Ordering

Identity

Billing

A BFF endpoint: aggregation and shaping only. No business rules, no writes it decides on its own.typescript
// mobile-bff: one request, one screen, exactly the fields it renders.
export async function GET(request: Request) {
  const principal = await authenticate(request); // identity comes from the edge

  const [enrolment, nextLesson, streak] = await Promise.all([
    learning.enrolmentSummary(principal.id),
    learning.nextLesson(principal.id),
    progress.streak(principal.id),
  ]);

  // Shaping for one screen. The decision about *what a streak is* lives in
  // the progress service; the BFF only decides what this screen displays.
  return Response.json({
    courseTitle: enrolment.courseTitle,
    percentComplete: enrolment.percentComplete,
    nextLesson: nextLesson && { slug: nextLesson.slug, title: nextLesson.title },
    streakDays: streak.days,
  });
}

In practice

Introducing BFFs to unblock two teams

A retail platform had one API team serving a web app, an iOS app and an Android app. The API team had a nine-week backlog, both mobile teams were blocked on field additions, and the mobile apps made an average of eleven requests per screen.

Constraints

  • One API team of four, nine-week backlog
  • Two mobile teams of five, blocked on the API team
  • Mobile screens averaging eleven requests, some on 3G networks
  • A partner API with three integrators must remain stable

Decision

Give the web team and the mobile teams a BFF each, owned and deployed by them. Keep the existing API as the partner-facing contract with its versioning intact. The API team became a services team owning the domain services behind the BFFs.

Why

The nine-week backlog was a structural queue rather than a capacity problem: presentation concerns for three clients were all flowing through one team. Moving presentation aggregation to the teams that own the presentation removed the queue for the majority of requests, and left the API team owning the thing only they could own — the domain services.

What it cost

Three backends now exist where one did, and roughly 30% of the aggregation code is similar across them. The team accepted that deliberately: the duplicated code has three independent reasons to change, which is exactly the case where the DRY module said duplication is cheaper than a shared abstraction. They also added an explicit rule — no business decision in a BFF — and a quarterly review comparing the three, and they were clear that this arrangement needs three teams to sustain it and would be wrong at half the size.

A mobile team asks for a new endpoint that returns "everything for the home screen"

As a developer

Adds the endpoint to the shared API, since that is where endpoints live, and it is a reasonable request that will reduce mobile round trips.

As an architect

Notices that the shared API is accumulating screen-shaped endpoints for one client, which is a shared component acquiring per-client presentation concerns. That is the pressure the BFF pattern exists to relieve — but it is only worth relieving if the mobile team can own and operate their own backend. If they cannot, screen-shaped endpoints in the shared API are the honest lesser evil, and the decision should be recorded as such rather than drifting.

Your organisation has one web client and one small internal admin tool. A developer proposes a BFF per client. Is this justified?Reveal

Almost certainly not, and the tell is that the pressure BFFs relieve is not present. That pressure comes from clients with genuinely conflicting needs — a mobile app fighting round trips, a partner needing stability, a web app iterating weekly — and from separate teams queueing behind a shared API. Two clients with similar needs and probably the same team have neither problem, so two BFFs would produce two deployables, two pipelines and duplicated aggregation to solve nothing. What is worth taking from the pattern even here is the principle: keep presentation shaping separate from domain logic, which can be a directory rather than a deployable. Revisit if a third client with different constraints arrives, or if a second team starts queueing.

Key takeaways

  • A single API serving several clients averages across conflicting requirements and satisfies none of them well.
  • A BFF is one backend per client experience, owned by the team that builds that experience.
  • A gateway is shared and handles cross-cutting concerns; a BFF is per-client and handles aggregation. Use both, in that order.
  • BFFs may aggregate and reshape; they must not make business decisions, or clients will diverge in behaviour.
  • The pattern is justified by conflicting client needs and by teams queueing behind a shared API — not by client count.