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:

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:

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:

The payload should remain small because:

Web Application

The web application requires richer information, including:

Desktop users generally expect a more detailed experience.

Admin Dashboard

An internal admin portal requires completely different information:

Most of this data should never be exposed to customers.

Without a BFF, a shared API typically ends up doing one of two things:

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:

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:

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:

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:

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:

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:

AspectMicroservices AloneMicroservices + BFF
API shapeOne-size-fits-all or filled with client conditionalsTailored for each client
Client couplingFrontends communicate with multiple servicesFrontends communicate with one BFF
Payload sizeOften over-fetchedReturns only required data
Team ownershipBackend team owns API contractsFrontend teams can evolve their BFF independently
Release velocityTeams may block one anotherTeams release independently
ComplexityClient-specific logic leaks into servicesAdditional 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:

When You Should Think Twice

Like every architectural pattern, BFF introduces additional complexity.

You should reconsider using it when:

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.