LS LOGICIEL SOLUTIONS
Toggle navigation

What Is Backend For Frontend?

Definition

A backend for frontend, usually shortened to BFF, is a dedicated backend service built to serve one specific client application, rather than a single general-purpose API expected to serve every client equally well regardless of its needs. Instead of a mobile app, a web app, and a partner integration all hitting the same generic API and each doing extra work on their side to reshape the response into what they actually need, each client gets its own BFF tuned precisely to its exact requirements. The BFF sits between the client and the underlying microservices or data sources, aggregating, reshaping, and filtering data specifically for that one frontend and nothing else. It is a pattern, not a specific product or framework, and teams implement it with whatever backend technology already fits their existing stack.

The reason the backend for frontend pattern exists is that different clients genuinely need different things from the same underlying data, and forcing them all through one shared API creates constant, low-grade friction that compounds over time. A mobile app on a slow connection wants a small, pre-aggregated payload with only the fields it will actually display on a small screen. A desktop web app might want richer data in a single call to avoid multiple round trips over a fast connection. A generic API trying to satisfy both ends up either over-fetching for mobile or requiring extra client-side transformation logic for web, and every change made to satisfy one client risks breaking or bloating the response for the other client depending on the same endpoint. The BFF pattern solves this by giving each client team real ownership of an API shaped entirely around their own product's needs.

What distinguishes a BFF from a normal backend service is that it is explicitly scoped to one consumer and typically owned by the same team that builds that consumer's frontend, not by a separate central team. It is not meant to be reused across clients the way a general API is; if two clients need the exact same shape of data, that's usually a signal they might not need separate BFFs at all, or that some of that shared logic actually belongs in a common service sitting beneath both BFFs. The BFF calls into shared microservices or databases underneath it, but the aggregation, filtering, and formatting logic specific to one client lives in that client's own BFF layer, not scattered across the client's frontend code or crammed awkwardly into a one-size-fits-all API everyone has to negotiate changes to. This distinction matters because it keeps the shared services beneath the BFFs genuinely generic and reusable, while all the messy, client-specific translation work stays contained in a layer built exactly for that purpose.

By 2026, the BFF pattern has become a standard part of how teams build for multiple client types, especially once a product has both a mobile app and a web app with meaningfully different needs, or once a company starts exposing APIs to partners with different requirements than its own first-party clients have. It grew out of large-scale engineering practices at companies with many distinct client types, but it has since become common well beyond that original scale, because the underlying problem, one API trying to please every client at once, shows up in mid-size products too, often earlier than teams expect. Teams weigh it against simpler alternatives like GraphQL, which can solve some of the same over-fetching problems without standing up a fully separate service per client, and the right answer often depends less on scale and more on how different each client's underlying business logic and error handling actually needs to be.

This page covers how a BFF sits between clients and backend services in practice, why giving each client its own tailored layer beats one generic API in the long run, how it compares to an API gateway and a GraphQL gateway, and where the added service and operational overhead is worth taking on versus where it just adds complexity nobody actually needed. The durable idea underneath the pattern is that an API designed for one specific consumer will always fit that consumer better than an API designed to please everyone at once, and understanding that tradeoff clearly lets a team decide, client by client, whether the extra service is genuinely worth building and operating.

Key Takeaways

  • A backend for frontend (BFF) is a dedicated API layer built to serve one specific client, rather than one generic API shared across every client.
  • It exists because different clients, mobile, web, partners, need data shaped differently, and a single shared API forces awkward compromises for all of them.
  • Each BFF is typically owned by the same team that owns the frontend it serves, and it calls into shared services underneath it for actual data.
  • BFF is not a replacement for shared microservices; it sits on top of them, doing client-specific aggregation and formatting work, nothing more.
  • The pattern earns its complexity when clients have meaningfully different needs; it is unnecessary overhead for products with only one client type to serve.

How a BFF Sits Between Clients and Backend Services

Picture a product with a mobile app and a web app, both needing data from five different microservices: user profiles, orders, inventory, recommendations, and payments. Without a BFF, each client calls all five services directly, handling the aggregation, error cases, and formatting differences in its own frontend code, duplicating that logic across both clients and coupling both frontends tightly to the internal structure of five separate services that were never designed with any single frontend's needs in mind.

With a BFF, the mobile app talks to exactly one thing: its own BFF. That BFF calls into the five microservices behind the scenes, combines their responses into one payload shaped exactly for what the mobile screen needs to render, handles partial failures gracefully (what happens if recommendations is down but the rest of the data is fine), and returns a single clean response the mobile client can consume with minimal logic of its own. The web app has its own separate BFF doing the equivalent work, shaped for what the web experience specifically needs, which might be a noticeably richer payload since bandwidth is less of a constraint there.

This means the client code gets dramatically simpler on both sides: it makes one call, gets back exactly what it needs to render the screen, and does not need to know or care that five different services exist underneath it at all. New engineers joining the mobile team can be productive quickly precisely because they only ever need to understand the shape of one API, not the internal topology of the whole backend estate. If one of those backend services changes its schema or gets split into two separate services later, the BFF absorbs that change entirely, and the client keeps working without any modification, as long as the BFF's contract with the client stays stable through the transition. This insulation is often the quiet, unglamorous reason a large-scale backend refactor can happen at all without forcing a coordinated release across every client app at the exact same time.

The tradeoff is that you now have another service to build, deploy, and monitor, one per client, each with its own lifecycle. That service needs its own on-call ownership, its own error handling logic, and its own performance characteristics understood in depth, and if the team building the mobile app doesn't also own its BFF directly, you've just recreated the same coordination problem the pattern was meant to solve in the first place, one layer removed and slightly better disguised.

Why One BFF Per Client Beats One Generic API

A generic API trying to serve every client at once tends to converge on a lowest-common-denominator shape: broad, generic fields that satisfy nobody particularly well, forcing every client to pick through a large, bloated response for the handful of fields it actually needs to render its own screens. This over-fetching is a real cost on mobile specifically, where every extra kilobyte affects load time on a slow or metered connection, and it is a real cost on the frontend team's side too, since they end up writing transformation logic client-side that arguably belongs on the server, closer to the data.

Worse, a shared API creates an ongoing coordination tax on every single change anyone wants to make. If the web team needs a new field added, that change goes into the same API the mobile team depends on for their own screens, and now the mobile team has to review, approve, or at least be aware of a change they didn't ask for and genuinely don't need for anything. Over time, shared APIs accumulate a long tail of fields nobody quite remembers the original purpose of, added for one client years ago and never removed because nobody's entirely sure what still quietly depends on them in production.

A BFF per client removes this coordination tax almost entirely for the aggregation and shaping logic specifically, since each team can evolve their own BFF on their own schedule without touching anyone else's code or roadmap. The web team can add a field to their BFF's response on a Tuesday afternoon without a single conversation with the mobile team, because the two BFFs are entirely independent artifacts even though they draw from exactly the same underlying shared services underneath.

This independence is the real value of the pattern, more so than any raw performance gain it delivers. Performance gains from a leaner payload are real but often fairly modest in practice; the bigger win is organizational, letting frontend-aligned teams move at their own pace instead of negotiating shared API changes with every other client team that happens to depend on the same generic endpoint they're touching. Teams that adopt BFF purely chasing the performance gain and skip the ownership change tend to be disappointed, since the payload gets leaner but the coordination friction that was really bothering everyone stays exactly the same.

BFF vs API Gateway vs GraphQL Gateway

An API gateway sits in front of a set of backend services and handles cross-cutting concerns that apply to every client equally: routing requests to the right service, authentication, rate limiting, and sometimes basic request transformation shared across the board. It typically serves all clients through the same routing rules and configuration, and while it can do light per-client customization in places, it is not designed to do the deep, client-specific aggregation work a BFF is built for. Many architectures use both together: an API gateway handling the cross-cutting infrastructure concerns, with individual BFFs sitting behind it for the client-specific logic each team owns.

A GraphQL gateway offers a genuinely different answer to the same over-fetching problem a BFF solves: instead of a separate service per client, one GraphQL endpoint lets each client specify exactly which fields it wants in a query, so a mobile client naturally gets a smaller response than a web client without needing separate backend code written specifically for each one. This avoids building multiple BFF services outright, but it shifts real complexity into schema design and query resolution instead, and it requires client teams to be genuinely comfortable writing and maintaining GraphQL queries rather than simply calling straightforward REST-style endpoints they're already familiar with.

The choice between BFF and GraphQL often comes down to how different clients' aggregation needs actually are, not just their field selection preferences. If clients mostly need the same underlying data with different fields included or excluded, GraphQL's field selection alone solves that well without extra infrastructure. If clients need genuinely different aggregation logic, different error handling per data source, or different combinations of services entirely for the same conceptual screen, a BFF's ability to run custom server-side logic per client tends to fit that situation better than trying to force that complexity into a single shared GraphQL schema.

Some architectures combine the two approaches deliberately: a GraphQL layer living inside each BFF, giving client teams the flexibility of field selection within a service that's still scoped and owned per client as before. This is more setup than either pattern alone would require, and it's usually only worth the investment once a product has enough distinct clients and enough backend complexity that both problems, client-specific aggregation and flexible field selection, are showing up at the same time and causing real friction.

Where BFF Fits and Where It Adds Unneeded Complexity

BFF fits well once a product has genuinely different client types with different data and performance needs, most classically a mobile app and a web app that display substantially different information to their users, or a public partner API that needs a fundamentally different contract entirely from your own first-party clients. It also fits well organizationally when different teams own different clients and want to move independently without constant coordination meetings through a shared central API team acting as a bottleneck.

It fits particularly well when aggregating data from many microservices is already a real, visible burden on client code today, since consolidating that aggregation logic into one place per client, rather than duplicating it across every client's own codebase separately, is a clear win regardless of how many distinct client types exist in the product portfolio. A good signal that a team has reached this point is when frontend developers start describing their job as spending as much time stitching together backend calls as they spend building the actual user interface.

It adds unneeded complexity for a product with a single client type and no realistic near-term plans for a second one, since building and owning a separate BFF service when there's only one frontend to serve just recreates the same API you'd have built anyway, with an extra deployment pipeline and monitoring surface added for no real benefit gained. In that situation, the "backend for frontend" is simply your backend, full stop, and giving it a special name doesn't change anything meaningful about how it should actually be built or operated.

It also adds real friction if BFFs end up owned by a central backend team rather than the frontend teams they're specifically meant to serve, since the whole point of the pattern is letting frontend-aligned teams control their own API surface without asking permission. A BFF owned by a separate team just re-creates the shared-API coordination problem under a slightly different name, with an extra service layered on top to maintain besides. Getting ownership right matters at least as much as getting the technical pattern right in the first place. A useful test during a design review is to ask who gets paged if the BFF fails at 2am; if the answer is a team other than the one that owns the client it serves, the ownership model needs revisiting before the pattern is trusted to deliver its intended benefit.

How to Implement a BFF Well

Assign ownership of each BFF to the same team that owns the client it serves, not to a central backend or platform team sitting apart from either frontend. This is the organizational core of the pattern, and skipping this step undermines most of the benefit entirely, since a BFF owned elsewhere just becomes another shared dependency carrying the same coordination overhead the pattern exists specifically to avoid in the first place.

Keep the BFF thin on business logic and focused narrowly on aggregation, formatting, and client-specific concerns like authentication flows or caching tuned for that one client. Business logic that would genuinely be needed by multiple clients belongs in the shared services underneath instead, not duplicated across two or three BFFs, since a BFF's job is to translate and combine, not to decide, wherever that decision applies equally to every client, or you'll end up maintaining the same rules in multiple places and watch them slowly drift apart from each other over time as each team makes its own small tweaks, until a pricing calculation or an eligibility rule quietly returns a different answer on mobile than it does on web, with nobody quite sure which one is correct.

Design for partial failure explicitly and up front, since a BFF calling into several backend services at once needs a clear, deliberate answer for what happens when one of them is slow or entirely unavailable. Decide, service by service, whether a failure should degrade gracefully, showing the screen without that particular section, or fail the whole request outright, and build that decision directly into the BFF rather than leaving it to be improvised under incident pressure at two in the morning. Document those decisions somewhere the whole team can find them, since the choice made for a recommendations service failing gracefully won't be obvious months later to whoever is debugging a related incident without that context in front of them.

Monitor each BFF as its own full production service with its own on-call ownership, error budgets, and performance targets, treating it with the same operational seriousness as any other production service, not as a thin proxy that doesn't warrant real attention. A BFF that goes down takes its entire client offline in one shot, and it deserves monitoring proportional to that genuinely large blast radius. Alerting thresholds, error budgets, and dashboards should exist for a BFF from the day it first goes live, not added retroactively after the first outage catches everyone by surprise.

Best Practices

  • Assign each BFF to the same team that owns the client it serves; centralizing BFF ownership recreates the coordination problem the pattern is meant to solve.
  • Keep business logic in shared services beneath the BFF, and use the BFF layer only for aggregation, formatting, and client-specific concerns.
  • Design explicit handling for partial failures across the services a BFF calls, deciding in advance what degrades gracefully versus what fails the request entirely.
  • Monitor each BFF as a full production service with its own on-call ownership, not as a lightweight proxy that gets ignored operationally over time.
  • Only build a separate BFF when clients have meaningfully different needs; a single-client product doesn't need the pattern applied at all.

Common Misconceptions

  • BFF is not a replacement for microservices; it's an aggregation layer that sits on top of them, calling into shared services underneath for actual data.
  • A BFF is not meant to be reused across multiple clients; if two clients need identical shapes, that logic likely belongs in a shared service instead.
  • Adopting BFF does not automatically fix organizational coordination problems if it's owned by a separate team from the client it's actually built to serve.
  • GraphQL is not a strict replacement for BFF; the two solve overlapping but genuinely different problems, and are sometimes combined for good reason.
  • A product with just one client type does not benefit from calling its normal API a "BFF"; the pattern's value comes specifically from having multiple distinct clients.

Frequently Asked Questions (FAQ's)

What is a backend for frontend?

A backend for frontend (BFF) is a dedicated API service built to serve one specific client application, aggregating and shaping data from underlying services exactly the way that one client needs it, rather than forcing every client through a single generic API built to please everyone.

Why not just use one API for every client?

A single shared API tends to satisfy no client particularly well, forcing over-fetching on lighter clients like mobile and creating an ongoing coordination bottleneck every time one client team needs a change that affects everyone else depending on the same shared endpoint.

Who should own a BFF, the frontend team or the backend team?

The same team that owns the client it serves should own its BFF, since the pattern's main benefit is letting that team move independently; a BFF owned by a separate team just recreates the coordination overhead the pattern is specifically meant to remove.

Is BFF the same thing as an API gateway?

No, an API gateway typically handles cross-cutting concerns like routing, authentication, and rate limiting across all clients equally, while a BFF does deep, client-specific aggregation and formatting for one particular client; many systems use both together in the same architecture.

Can GraphQL replace the need for a BFF?

Sometimes, since GraphQL lets each client request exactly the fields it needs from one shared endpoint, which solves over-fetching without a separate service per client; but it doesn't replace a BFF well when clients need genuinely different aggregation logic, not just different fields returned.

Do I need a BFF if my product only has a website?

No, if there's only one client type, a dedicated BFF adds a deployment and ownership burden without a real benefit gained; in that case your normal backend API already serves the exact role a BFF would otherwise play.

How many BFFs should a product have?

Generally one per meaningfully distinct client, such as one for mobile, one for web, and possibly one for a partner integration; clients with genuinely identical needs shouldn't each get their own separate BFF, since that just adds duplicate services without any real benefit.

What happens if a backend service a BFF depends on goes down?

That depends entirely on how the BFF was designed to handle partial failure ahead of time; a well-built BFF degrades gracefully, returning what it can and flagging or omitting the parts it couldn't fetch, rather than failing the entire client request over one unavailable dependency.

Is the BFF pattern only useful for large companies?

No, while it originated at companies managing many distinct client types at scale, the underlying problem it solves, one API poorly serving several different clients at once, shows up in mid-size products too, and the pattern scales down reasonably well once a team has even two meaningfully different clients.