A smartwatch and a desktop dashboard both show your fitness stats — but they have wildly different needs. The watch wants three numbers on a tiny screen over a flaky connection. The dashboard wants rich charts, history, and detail. Force both to use the same API and someone loses: either the watch downloads a payload it can't use, or the dashboard makes ten calls to assemble one screen.
Backends for Frontends says: stop compromising. Give each client its own backend, tailored to exactly what that experience needs.
The problem
The classic approach is one general-purpose API that every client shares — mobile, web, third-party integrators, all of them. It sounds efficient, but it slowly becomes a tar pit. Different clients want different data shapes, different fields, different amounts of detail, so the API grows endless optional parameters and bloated responses trying to please everyone.
Worse, the clients are now coupled through that shared API. A change the mobile team needs can break the web app. Nobody fully owns it, so it ossifies — every change requires cross-team coordination, and the API ends up fitting everyone equally badly.
- ClientMobile and web have different needs but must share the same endpoints and shapes.
- General-purpose APIGrows endless options and bloated responses trying to please everyone; clients are coupled through it.
- ServicesThe downstream services the single shared API fronts for every client at once.
How it works
Instead of one shared backend, you build a separate backend per frontend: a mobile BFF, a web BFF, maybe a partner-API BFF. Each one is a thin service that sits in front of your downstream microservices and shapes everything for its one client. The mobile BFF returns small, trimmed payloads in a single call; the web BFF assembles rich, detailed responses.
Each BFF typically does aggregation — fanning out to several downstream services and stitching the results into exactly the shape its client wants, so the device makes one request instead of ten. Crucially, each BFF is owned by the team that owns its frontend, so they can evolve it freely without stepping on anyone else. The diagram below shows two clients, each talking to its own dedicated backend, which both draw on the shared downstream services.
- ClientA frontend with its own needs — a small mobile screen or a rich web dashboard.
- BFFA backend tailored to one frontend; it shapes and aggregates data for that client.
- Shared ServicesThe downstream microservices both BFFs draw on for the actual data.
Tailor the experience, not the business logic. A BFF should handle shaping, aggregating, and presentation concerns. Core domain rules belong in the downstream services — if real business logic starts piling up in each BFF, you'll be duplicating it across all of them.
When to use it
BFF is a great fit when your clients have genuinely different needs — a mobile app, a web app, and a partner API really do want different things — and when separate teams own those frontends and want to move at their own pace. It's a natural evolution of the API gateway: instead of one gateway for all, you get one purpose-built entry point per experience.
The cost is duplication and proliferation. Each BFF is another service to deploy, monitor, and secure, and common logic can get repeated across them (factor truly shared bits into a library or a downstream service). If all your clients want essentially the same data in the same shape, a single well-designed API is simpler — don't split backends just because you can.