The Problem That Started It All
Picture this. Your team has just finished breaking a monolithic application into 15 independent microservices. Everyone is happy. Then the mobile team comes to you and says:
"Our app is calling six different services just to render the home screen, and half the data we get back we don't even need."
A week later, the web team raises a similar concern. Their page requires slightly different data, structured differently, with a few additional fields that the mobile app doesn't care about.
Now you're faced with difficult choices:
Should you modify the microservice APIs to satisfy the mobile team? That could break the web application.
Should you add optional fields everywhere? That quickly fills your services with client-specific logic unrelated to their business responsibilities.
This exact challenge—first experienced at scale by streaming and e-commerce companies supporting many different client applications—led to the creation of the Backend for Frontend (BFF) architectural pattern.
So, What Exactly Is a BFF?
In simple terms, a Backend for Frontend (BFF) is a dedicated backend layer built specifically for a single frontend application or client type.
Instead of every client—such as a web application, mobile app, smart TV app, or third-party integration—communicating directly with shared microservices, each client communicates with its own backend layer.
That backend has one primary responsibility:
Call the required microservices.
Aggregate and reshape the returned data.
Return exactly the data that particular frontend needs, in the format it expects.
Think of a BFF as a personal translator standing between your frontend and your microservices. The frontend doesn't need to understand the complexity of multiple backend services—it simply communicates with its dedicated translator, which knows exactly what that frontend expects.
Web App Mobile App Smart TV App
| | |
Web BFF Mobile BFF TV BFF
| | |
\________________|_________________/
|
┌───────────────┼────────────────┐
Orders Service Catalog Service User Service
Notice something important.
There is still only one set of core microservices.
The BFF does not replace them. It simply sits in front of them as a client-specific layer.
A General Example
Imagine an e-commerce platform.
Different clients require different data.
Mobile App
The mobile application only needs:
Product name
Price
Thumbnail image
Star rating
The payload should remain small because:
Web Application
The web application requires richer information, including:
Product name
Price
Full image gallery
Detailed specifications
Related products
Customer reviews
Desktop users generally expect a more detailed experience.
Admin Dashboard
An internal admin portal requires completely different information:
Product name
Price
Stock count
Supplier information
Audit logs
Most of this data should never be exposed to customers.
Without a BFF, a shared API typically ends up doing one of two things:
Returning everything to everyone, creating unnecessarily large payloads.
Filling business services with conditional logic such as:
if (clientType == "mobile")
{
...
}
Now your Product Service knows about mobile apps, web apps, and admin dashboards—responsibilities it should never have.
With the BFF pattern, you instead build three lightweight layers:
Mobile BFF
Web BFF
Admin BFF
Each one calls the same Product Service, Inventory Service, and Review Service, but shapes the response differently for its own client.
A Simple C# Example
The following ASP.NET Core Minimal API demonstrates a Mobile BFF that aggregates data from two microservices into a lightweight response.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient("ProductService", c =>
c.BaseAddress = new Uri("https://catalog-service/"));
builder.Services.AddHttpClient("ReviewService", c =>
c.BaseAddress = new Uri("https://review-service/"));
var app = builder.Build();
app.MapGet("/mobile/products/{id}", async (string id, IHttpClientFactory factory) =>
{
var productClient = factory.CreateClient("ProductService");
var reviewClient = factory.CreateClient("ReviewService");
var productTask = productClient.GetFromJsonAsync<ProductDto>($"products/{id}");
var reviewTask = reviewClient.GetFromJsonAsync<ReviewSummaryDto>($"reviews/{id}/summary");
await Task.WhenAll(productTask, reviewTask);
// Shape the response exactly how the mobile app wants it.
var response = new
{
productTask.Result!.Name,
productTask.Result.Price,
Thumbnail = productTask.Result.Images.First(),
Rating = reviewTask.Result!.AverageRating
};
return Results.Ok(response);
});
app.Run();
Notice what this API does not contain:
No business logic
No database
No domain rules
Its responsibility is simply:
That is the essence of the BFF pattern.
Real-World Use Cases
The BFF pattern is widely used by large technology companies.
Netflix
Netflix popularized the pattern because it serves content across hundreds of device types, including:
Smart TVs
Gaming consoles
Mobile phones
Tablets
Web browsers
Each platform has different screen sizes, bandwidth limitations, and rendering capabilities.
SoundCloud
SoundCloud is widely credited with introducing the term Backend for Frontend (BFF) after discovering that their web and mobile teams continually conflicted over a shared API.
Spotify
Spotify uses BFF-style layers so its desktop, web, and mobile applications can evolve independently without forcing every client to share identical API contracts.
Banking and FinTech
Many banking applications maintain separate BFFs for:
Mobile banking apps
Web banking portals
This allows each platform to optimize:
Isn't This Just Microservices?
No.
This distinction is important because the two concepts solve completely different problems.
Microservices
Microservices focus on organizing the backend by business capability.
Examples include:
Orders
Payments
Inventory
Users
Each service typically owns:
Backend for Frontend
A BFF focuses on how frontend applications consume those services.
It sits on top of the existing backend and presents each client with an API tailored specifically for its needs.
The relationship looks like this:
| Aspect | Microservices Alone | Microservices + BFF |
|---|
| API shape | One-size-fits-all or filled with client conditionals | Tailored for each client |
| Client coupling | Frontends communicate with multiple services | Frontends communicate with one BFF |
| Payload size | Often over-fetched | Returns only required data |
| Team ownership | Backend team owns API contracts | Frontend teams can evolve their BFF independently |
| Release velocity | Teams may block one another | Teams release independently |
| Complexity | Client-specific logic leaks into services | Additional BFF layer to maintain |
It is not:
BFF versus Microservices
Instead, it is:
Microservices with or without a Backend for Frontend layer.
The two patterns complement one another.
Where BFF Shines
A Backend for Frontend works particularly well when:
You support multiple client types such as web, mobile, smart TVs, or partner APIs.
Different clients require significantly different data.
Frontend teams want to release independently.
Your services are accumulating platform-specific conditional logic.
Mobile applications are making numerous network calls that could be combined into one.
Different clients require different authentication or security approaches.
When You Should Think Twice
Like every architectural pattern, BFF introduces additional complexity.
You should reconsider using it when:
You have only one frontend application.
Your team is too small to maintain multiple backend layers.
Every client requires nearly identical data.
Your microservices architecture is still unstable.
The BFF begins accumulating business logic that belongs inside domain services.
A BFF should remain thin and focused on orchestration rather than business behavior.
A Quick Gut Check
Before introducing a BFF, ask yourself:
"If my mobile application's data requirements changed tomorrow, would I have to modify APIs that my web application also depends on?"
If the answer is yes, a BFF is likely worth considering.
If the answer is no, your current architecture may already be sufficient.
Wrapping Up
The Backend for Frontend pattern exists because a single API serving many different clients eventually becomes difficult to maintain. As applications expand across web, mobile, smart TVs, partner integrations, and other platforms, each client naturally develops unique requirements.
A BFF complements a microservices architecture by acting as a client-specific orchestration layer. It aggregates data from multiple services, reshapes responses, reduces unnecessary payloads, and allows frontend teams to evolve independently while keeping core business services clean and focused.
When applied appropriately, the pattern improves developer productivity, simplifies frontend development, and preserves clear separation of concerns. When applied unnecessarily, however, it can introduce additional maintenance overhead and duplicated orchestration logic. As with any architectural decision, success comes from recognizing when the problem genuinely calls for a Backend for Frontend layer.