Backend for Frontend (BFF)

How to build specialized backends per client type to optimize the experience of each platform without coupling the internal services.

What problem it solves

In a microservices architecture with a single API Gateway, every client (web, mobile, IoT, smart TV) consumes the same API. But each client has very different needs:

  • Mobile: Needs compact responses (limited bandwidth), aggregated data in few calls
  • Web SPA: Can handle more data, needs pagination and advanced filters
  • IoT: Only needs a minimal subset of data with lightweight protocols
Problema con un solo API Gateway:
  Mobile App ──► API Gateway ──► Microservicios
  Web App    ──► (misma API)
  IoT Device ──► (misma API)
  
  La API devuelve TODOS los campos para TODOS los clientes
  Mobile recibe datos que no necesita → desperdicio de ancho de banda
  Web no puede pedir datos extra sin afectar a mobile
  Cada cambio en la API afecta a todos los clientes

The result is a “one-size-fits-all” API that serves no client well, or an API full of conditional parameters (?platform=mobile&fields=name,price) that becomes hard to maintain.

How it works

The BFF pattern proposes creating a dedicated backend for each type of client. Each BFF is a lightweight service that acts as an intermediary between its specific client and the internal microservices.

Con BFF:
  Mobile App ──► BFF Mobile  ──┐
  Web App    ──► BFF Web     ──┤──► Microservicios
  IoT Device ──► BFF IoT     ──┘
  
  Cada BFF adapta las respuestas a su cliente
  Cada equipo de frontend controla su BFF
  Los microservicios no cambian

BFF responsibilities

ResponsibilityDescriptionExample
AggregationCombine data from multiple servicesMobile dashboard with 3 services in 1 call
TransformationAdapt data format and structureTrim fields for mobile, expand for web
OrchestrationCoordinate service calls in orderLogin → profile → preferences in sequence
Client-specific cachingCache according to client patternsMobile caches catalog for 10 min, web for 2 min
AuthenticationHandle client-specific authOAuth for web, API key for IoT

Example: product endpoint

Microservicio Product Service devuelve:
{
  "id": "P001",
  "name": "Laptop Pro",
  "description": "Laptop de alto rendimiento...",
  "specs": { "cpu": "i9", "ram": "32GB", "storage": "1TB" },
  "images": ["url1.jpg", "url2.jpg", "url3.jpg", "url4.jpg"],
  "reviews": [...50 reviews...],
  "relatedProducts": [...10 productos...],
  "inventory": { "warehouse1": 50, "warehouse2": 30 },
  "pricing": { "base": 1500, "discount": 10, "tax": 15 }
}

BFF Mobile devuelve:
{
  "id": "P001",
  "name": "Laptop Pro",
  "image": "url1_thumb.jpg",
  "price": "$1,350",
  "rating": 4.5
}

BFF Web devuelve:
{
  "id": "P001",
  "name": "Laptop Pro",
  "description": "Laptop de alto rendimiento...",
  "specs": { "cpu": "i9", "ram": "32GB", "storage": "1TB" },
  "images": ["url1.jpg", "url2.jpg", "url3.jpg", "url4.jpg"],
  "reviewSummary": { "average": 4.5, "count": 50 },
  "price": { "original": 1500, "final": 1350, "discount": "10%" },
  "relatedProducts": [...3 productos...]
}

BFF ownership

A key principle of the pattern is that the frontend team owns its BFF. This enables:

  • The mobile team decides what data it needs and how to structure it
  • Changes to the UI don’t require coordinating with other teams
  • Each BFF evolves at the pace of its client

Advantages

  • Per-client optimization: Each platform receives exactly the data it needs
  • Team autonomy: The frontend team controls its backend without depending on others
  • Independent evolution: Changes to the mobile API don’t affect web or IoT
  • Performance: Less data transferred, fewer calls from the client
  • Client simplicity: The frontend consumes an API designed specifically for it
  • Granular security: Each BFF can implement client-specific security policies

Trade-offs / Drawbacks

  • Code duplication: Similar logic may be repeated across BFFs (mitigable with shared libraries)
  • More services to maintain: Each BFF is an additional service that needs deployment and monitoring
  • Consistency: Different BFFs may return inconsistent data if not coordinated
  • Organizational complexity: Requires teams with full-stack capability (frontend + its BFF)
  • Latency: An extra hop between the client and the microservices
  • Risk of a monolithic BFF: If the BFF grows too large, it turns into a mini-monolith

When to use it

  • Multiple types of client with very different data needs
  • Frontend teams that need autonomy to evolve their API
  • Mobile applications where bandwidth and the number of calls matter
  • When a single API Gateway becomes too complex with per-client conditional logic
  • Organizations with dedicated teams per platform (mobile team, web team)

When to avoid it

  • A single type of client (web only, or mobile only)
  • Clients with very similar data needs
  • Small teams where maintaining multiple BFFs is not justified
  • When an API Gateway with simple transformations is enough
  • Prototypes or MVPs where development speed is the priority

Common technologies and implementations

CategoryOptions
FrameworksExpress/Fastify (Node.js), Spring Boot (Java), ASP.NET Core (.NET)
GraphQL as BFFApollo Server, Hasura, Strawberry (Python)
API Gateway + BFFKong + BFF services, AWS API Gateway + Lambda
Internal communicationgRPC between BFF and microservices, REST, messaging

Relationship with other patterns

  • API Gateway: The BFF is a specialization of the API Gateway per client type
  • Microservices: BFFs consume internal microservices and adapt them
  • Anti-Corruption Layer: The BFF can act as an ACL between the frontend and legacy services
  • Circuit Breaker: Each BFF should implement circuit breaking toward the services it consumes

Next steps

The BFF gives you granular control over each client’s experience. To understand how to decompose the services the BFF consumes, explore the Microservices pattern. To protect communication between the BFF and external services, review the Anti-Corruption Layer.