Design Patterns & Practices  

Backend for Frontend (BFF): Why Your Microservices Need a Translator

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:

  • Mobile networks may be slower.

  • Screen space is limited.

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:

  • Calling services

  • Aggregating responses

  • Returning data in the exact format required by the mobile application

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:

  • Data payloads

  • Authentication mechanisms

  • Security requirements

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:

  • Its own database

  • Its own deployment pipeline

  • Its own business logic

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:

  • 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.