Articles

What Is the Backend-for-Frontend (BFF) Pattern?

A backend-for-frontend (BFF) is a dedicated backend layer for one client type — shaping, aggregating, and simplifying calls to shared downstream APIs.

Takina Takina · · 4 min read
Dark-themed code editor showing backend service code

A backend-for-frontend, or BFF, is a backend service built and owned by a specific frontend team to serve that frontend’s needs — as opposed to a single general-purpose API that every client (web, iOS, Android, partners) has to share. Instead of a mobile app and a web app both calling the same generic endpoints and each doing their own data massaging client-side, each gets its own thin backend tailored to exactly what it needs to render.

Why a shared API starts to hurt

A single backend API serving multiple clients tends toward one of two bad outcomes. Either it stays generic and every client ends up making several round trips and stitching the results together itself, or it accumulates client-specific fields and query parameters until the API becomes a tangle of special cases nobody wants to touch. A mobile app on a slow connection wants a small, denormalized payload in one request; a desktop web app rendering a dense dashboard might want several resources joined together; an internal admin tool wants raw fields with no shaping at all. Forcing all three through one contract makes every change a negotiation.

This is the same tension that shows up in the REST vs GraphQL debate — GraphQL lets each client ask for exactly the shape it needs from a single endpoint. A BFF solves the same problem from the other direction: instead of one flexible endpoint, you get several purpose-built ones.

How a BFF fits into the architecture

Web client   →  Web BFF     ─┐
Mobile client → Mobile BFF   ─┼─→  Shared domain services / APIs
Partner API  →  Partner BFF ─┘

Each BFF sits between its client and the shared backend — microservices, a monolith, or a mix — and does the work of:

  • Aggregating multiple downstream calls into one response the client can render immediately.
  • Shaping the payload to match what that client’s UI actually needs, dropping fields it doesn’t use.
  • Translating protocols or auth schemes where the client and the backend don’t speak the same language.
  • Absorbing client-specific logic (pagination style, caching headers, feature flags) that has no business living in the shared domain services.

The BFF is typically owned by the same team that owns the frontend, which is the point: frontend engineers can change their BFF’s contract without waiting on, or destabilizing, a shared API that other clients depend on.

BFF vs API gateway vs a single shared API

Single shared APIAPI gatewayBackend-for-frontend
OwnershipCentral backend teamPlatform/infra teamFrontend team, per client
ShapeOne generic contractRouting, auth, rate limiting for all clientsTailored to one client’s UI
Business logicSomeLittle to noneClient-specific aggregation logic
Change couplingHigh — every client shares riskLow for routing, none for domain logicLow — isolated per client

An API gateway and a BFF are often confused because both sit in front of backend services, but they solve different problems. A gateway is typically generic infrastructure — routing, authentication, rate limiting — applied uniformly across all traffic. A BFF is client-specific application logic. In practice, many systems use both: a gateway at the edge for cross-cutting concerns, and a BFF behind it per client for shaping and aggregation.

Where the aggregation logic actually lives

Consider a product page that needs pricing, inventory, reviews, and recommendations — four different downstream services in a microservices architecture. Without a BFF, the client itself has to call all four and merge the results, meaning every client reimplements the same merge logic, pays for four round trips (or more, over a slow mobile connection), and has to handle four different partial-failure cases. With a BFF, the client makes one call; the BFF fans out to the four services, merges the results server-side where the network between services is fast, and returns one shaped payload. The complexity doesn’t disappear — it just moves to a place that’s easier to change without touching every client.

That relocation is also what makes a BFF a good fit for gradually decomposing a monolith. Rather than requiring every client to migrate to new microservice endpoints simultaneously, a BFF can absorb the difference: it keeps talking to the client the same way while its own internals shift from calling the monolith to calling new services underneath, one piece at a time.

The tradeoff: more services, less coupling

The BFF pattern trades operational simplicity for team autonomy. You now have multiple backend services to deploy, monitor, and secure instead of one — and if two BFFs independently reimplement the same aggregation logic, you’ve just moved duplication rather than removed it. It fits naturally with a serverless deployment model, since each BFF is often thin enough to run as a small set of functions rather than a standalone service that needs its own scaling story.

It tends to pay off most in organizations with genuinely different clients — a mobile team, a web team, and a partner-integrations team, each with different release cycles and different needs from the data. It’s usually overkill for a single web app talking to its own backend; in that case, React Server Components or a similar server-rendering layer often absorbs the same aggregation work without a separate service at all.

The takeaway

A backend-for-frontend is a thin, client-owned backend that aggregates and shapes calls to shared downstream services, so each client — web, mobile, partner — gets exactly the payload its UI needs without forcing one API contract to serve everyone. It reduces coupling between frontend teams and shared services at the cost of running more backend surface area, and it complements rather than replaces an API gateway sitting in front of it.

The Lycoris Team The Lycoris Team · · 4 min read

API Versioning Strategies Explained

URI paths, custom headers, and content negotiation are the three common ways to version an API. Tradeoffs of each, and how to avoid breaking clients.

#Web Development #Developer Tools #Backend
Takina Takina · · 4 min read

HTTP Status Codes Explained: A Practical Guide

HTTP status codes are three-digit responses that tell a client what happened to its request. A practical tour of the codes that actually matter.

#Web Development #Networking #Backend