A Backend for Frontend (BFF) is a dedicated backend service built for one specific frontend. Instead of every client (web, iOS, Android, third-party) talking to the same general-purpose backend, each one gets its own server-side layer that aggregates and reshapes data from your microservices into exactly the payload that interface needs.
Sam Newman named and popularized the pattern in 2015, drawing on work done at SoundCloud. More than a decade later, the BFF pattern is still a standard tool for teams running microservices behind multiple client apps, and Microsoft documents it as a core cloud architecture pattern.
The problem a BFF solves
Picture a system that started with a single web app and a single backend. The backend exposed REST endpoints, the web app consumed them, and life was simple. Then the company shipped a mobile app. Then a partner integration. Then a smartwatch widget. Suddenly four very different clients are all pulling from the same backend, and that backend is trying to please everyone at once.
This creates two recurring problems.
Over-fetching and under-fetching. A general-purpose endpoint returns a fixed shape of data. A desktop dashboard might want the full customer record with order history, recommendations, and account settings in one response. A mobile app on a flaky cellular connection wants three fields and nothing more. When both hit the same endpoint, one of them gets the wrong amount of data. The mobile client either downloads a bloated payload it has to discard (over-fetching) or has to make several extra round trips to assemble what it needs (under-fetching).
Chatty clients. When a backend is not tailored to a screen, the client compensates by making many calls. A mobile home screen that needs profile data, a notifications count, and a feed might fire three or four separate requests to three or four microservices, then stitch the results together on-device. Every extra round trip costs latency and battery, and orchestration logic leaks into the client where it is hard to test and version.
The root tension is organizational as much as technical. A shared backend has competing demands from every frontend team. One team’s change has to be validated against every other team’s needs before it ships, which turns the backend into a bottleneck and a source of cross-team friction.
How the BFF pattern works
The BFF pattern introduces a thin server-side layer that sits between one frontend and your downstream services. Each interface gets its own backend.
[ Web app ] ---> [ Web BFF ] ---\
[ iOS app ] ---> [ iOS BFF ] -----> [ Microservices ]
[ Android app] ---> [ Android BFF ] ---/
Each BFF does three jobs for its client:
- Aggregate. It calls the downstream microservices the screen needs and combines their responses, so the client makes one request instead of five. This is API aggregation applied to a single user experience. If you want the general version of that idea, see our explainer on the API aggregator pattern.
- Reshape. It trims fields, renames things into client-friendly terms, flattens nested structures, and formats values the way that interface expects. The mobile BFF returns lean payloads; the desktop BFF returns rich ones.
- Translate. It handles client-specific concerns such as pagination strategy, response caching tuned to that client, and protocol choices, without forcing those decisions onto the shared services beneath.
The downstream microservices stay general-purpose and frontend-agnostic. They expose clean, reusable capabilities. The BFF is where client-specific shaping lives, which keeps that logic out of both the microservices and the client app. If you are new to the service layer underneath, our overview of microservices versus APIs and the move from a monolith to microservices sets the context.
One BFF per client experience
Newman’s core guidance is short: one experience, one BFF. If your iOS and Android apps offer meaningfully different experiences, give each its own BFF. If a web app and a mobile app diverge, the same rule applies.
The point of the rule is to keep each BFF focused. The moment a single BFF tries to serve two clients with different needs, it starts to accumulate conditional logic (“if mobile, return this; if web, return that”), and you are back to a general-purpose backend with all the same coordination problems. A focused BFF stays small, which is the property that makes the whole pattern pay off.
There is a sensible exception that Newman himself draws from SoundCloud: when one team owns two similar clients, such as iOS and Android apps that share almost the same experience, it can be reasonable to share a single mobile BFF between them. The deciding factor is ownership and similarity, not platform names. The rule is a default, not a law.
Ownership belongs to the frontend team
A BFF is not a layer the platform team builds and hands off. The frontend team that owns the client owns its BFF. This is the second half of what makes the pattern work.
When the frontend team owns the BFF, they control its release cadence, choose its language and runtime, prioritize its backlog, and ship changes to the client and its backing service together. A UI change that needs a new aggregated endpoint does not require filing a ticket with a separate backend team and waiting for it to clear that team’s queue. The team that feels the pain owns the fix.
This autonomy is the real win. The BFF moves the boundary so that client-specific decisions are made by the people responsible for the client, which is exactly where API-led connectivity thinking puts the “experience” tier.
BFF vs API gateway
This is the comparison most teams trip on, because a BFF and an API gateway look similar from a diagram. Both sit between clients and services. Both can route and aggregate. But they answer different questions.
An API gateway is a general-purpose entry point that handles cross-cutting concerns for all traffic: authentication, rate limiting, routing, TLS termination, and request logging. It is owned by a platform or infrastructure team and is deliberately client-agnostic. One gateway serves everyone the same way.
A BFF is the opposite. It is client-specific by design, owned by a frontend team, and its whole purpose is to be different for each interface. It is the place where one client’s payload shaping lives, not a shared chokepoint.
The two are not rivals. In a common production layout, an API gateway sits in front, handling auth and rate limiting and monitoring for all traffic, and then routes each client to its dedicated BFF behind the gateway. Microsoft’s reference architecture shows exactly this: a gateway managing cross-cutting concerns, with one serverless BFF per client behind it. Use the gateway for what is the same across clients, and a BFF for what is different. (We cover the deep version of this contrast in a separate article; here it is enough to know they sit at different layers and answer different needs.)
For the surrounding gateway landscape, these published comparisons help: API management vs API gateway, API gateway vs load balancer, and service mesh vs API gateway.
When to use a BFF
The pattern earns its keep when these conditions hold:
- You have multiple, genuinely different clients. Web plus mobile plus a partner integration, each with distinct data needs. The more the experiences diverge, the more a BFF helps.
- A shared backend has become a bottleneck. If every frontend change forces cross-team negotiation, splitting client-specific shaping into per-team BFFs removes the coordination tax.
- You want client-optimized payloads. Mobile needs lean responses and aggressive caching; desktop wants rich aggregated data. A BFF lets you optimize each without compromise.
- A language fits one frontend better. A team can build its BFF in the runtime that suits its client, independent of what the other BFFs use.
When not to use a BFF
The pattern is not free, and there are clear cases where it adds cost without payback:
- You only have one client. With a single interface, a BFF is just an extra hop. Build a normal backend.
- Your clients make the same requests. If web and mobile want nearly identical data in the same shape, separate BFFs duplicate effort for no benefit. Consolidate instead.
- GraphQL already solves your shaping problem. With GraphQL, each client queries exactly the fields it needs from a single endpoint, which covers much of what a BFF does for payload shaping. If you have a GraphQL layer with frontend-specific resolvers, a separate BFF tier often adds no value. See what GraphQL is to judge whether it fits before adding a BFF tier.
- A gateway plus microservices is enough. For simpler systems, an API gateway in front of well-designed microservices can deliver acceptable results without a dedicated per-client tier.
The honest downsides
Even when a BFF is the right call, you take on real costs. Going in with eyes open is part of using the pattern well.
Code duplication. This is the headline trade-off, and Microsoft’s documentation calls it out directly. When three BFFs all need to call the same authentication check or format the same date the same way, that logic tends to get written three times. You are trading duplication for tailoring. The fix is discipline: keep genuinely shared logic in libraries the BFFs import, and reserve the BFF itself for client-specific shaping. Push true cross-cutting concerns (auth, rate limiting, monitoring) up to the gateway rather than re-implementing them per BFF.
More services to operate. Each BFF is another deployable unit with its own lifecycle, pipeline, on-call rotation, and security surface. More services means more operational overhead.
An extra network hop. Clients no longer talk to services directly. The BFF adds a hop, and that can add latency. It is usually a worthwhile trade because the BFF removes several client round trips, but it is a cost to measure, not assume.
Risk of the BFF growing bloated. If a BFF starts serving multiple clients or absorbing business logic that belongs in the microservices, it drifts back toward the general-purpose backend you were trying to escape. Keep it thin.
Keeping BFF contracts in sync with Apidog
The hard part of running BFFs in practice is the contracts. Each BFF exposes its own client-facing API, and it also depends on the contracts of the microservices beneath it. That is a lot of moving interfaces across teams that own different layers, and drift between them is where bugs and broken clients come from.

This is where Apidog fits the workflow. Apidog is an API design, testing, mocking, and documentation platform, so each BFF’s API contract has a single home that the frontend and backend teams can both work against:
- Design the contract first. Define each BFF endpoint and its request and response schema in Apidog’s visual designer with OpenAPI underneath, so the client-facing shape is agreed before code is written. This is the contract-first approach applied to the BFF layer, and it keeps the API contract explicit.
- Mock it before it exists. The frontend team can start building against an Apidog smart mock of the BFF the day the contract is agreed, without waiting for the BFF or its downstream services to be ready.
- Test the contract. Apidog’s automated tests and assertions verify that each BFF returns the aggregated, reshaped payload its client expects, and they fit into CI so a downstream change that breaks a BFF response gets caught early.
- Document for both sides. Apidog auto-generates interactive docs from the contract, so the frontend team reading the BFF’s API and the backend team owning the services beneath share one source of truth.
To be clear about scope: Apidog does not build, host, or run your BFF, and it is not an API gateway. It is where you design, mock, test, and document the API contract that each BFF stands behind, which is what keeps frontend and backend teams in sync as the BFFs evolve. Treating each BFF as a product with a stable, well-documented contract is what makes the pattern sustainable.
FAQ
Is a BFF a microservice? A BFF is a server-side service, and in a microservices setup it usually runs as one. But its job is different from a typical microservice. A microservice owns a business capability and stays client-agnostic; a BFF owns one client’s experience and exists to aggregate and reshape those microservices for that client. It is an experience-layer service, not a business-capability service.
How many BFFs should I have? The default is one per distinct client experience: one for web, one for iOS, one for Android, and so on. Combine two only when a single team owns clients with nearly identical needs. Split further when one BFF starts accumulating per-client conditional logic.
Does GraphQL replace the BFF pattern? It can, for the payload-shaping part. GraphQL lets each client request exactly the fields it needs from one endpoint, which covers over-fetching and under-fetching without a per-client backend. If you have GraphQL with frontend-specific resolvers, a separate BFF tier often adds little. BFFs still help when you need per-client orchestration, protocol translation, or runtime choices that a shared GraphQL server cannot easily provide.
Can I use a BFF and an API gateway together? Yes, and it is common. The API gateway handles concerns shared across all clients, such as authentication, rate limiting, and monitoring, and routes traffic to the right BFF. Each BFF handles what is specific to its client. They sit at different layers and do different jobs.
Who should own the BFF? The frontend team that owns the client. That ownership is central to the pattern. It lets the team ship UI changes and the backing endpoints together, choose its own runtime, and move without waiting on a separate backend team’s queue.
Does a BFF add latency? It adds one network hop, which has a cost. In practice it usually reduces total client latency, because it replaces several client-to-service round trips with one client-to-BFF request and lets the BFF call services in parallel close to them. Measure it for your workload rather than assuming either way.



