Backend for Frontend (BFF) Pattern in Microservices

Arpit Bhayani

Arpit Bhayani

Jul 04, 2022 • 7 min read

Play

Introduction: The Multi-Client Challenge

When scaling an application from a single desktop web interface to a multi-platform ecosystem—such as native mobile applications (iOS/Android), smart devices, voice assistants (e.g., Amazon Alexa), or legacy third-party integrations—backend architectures face significant design challenges.

In a standard monolithic or microservices setup, a single unified endpoint often serves client requests. For instance, in an e-commerce platform, rendering a product details page requires retrieving:

  • Product metadata (title, description, brand)
  • Pricing and available SKU variants (colors, sizes)
  • Active seller listings
  • Frequently Asked Questions (FAQs)
  • Customer reviews and ratings

A unified endpoint such as GET /v1/product/:id aggregates this information and returns a single, comprehensive JSON payload. This design minimizes round-trips for desktop web clients, where screen real estate is vast and bandwidth is relatively unconstrained.

However, this model breaks down when applied indiscriminately across varied client types.


The Problem with Unified APIs

flowchart LR
    Web[Desktop Web Client] -->|GET /v1/product/:id| Monolith[Core Backend API]
    Mobile[Mobile Client] -->|GET /v1/product/:id| Monolith
    Alexa[Voice Assistant / Alexa] -->|GET /v1/product/:id| Monolith
    Monolith --> DB[(Database)]

1. The Mobile Screen Real Estate Constraint

Mobile screens have limited display space compared to desktop browsers. When a user opens a product page on a mobile device, only critical data (image, title, price, buy button) fits within the initial viewport. Non-essential sections, such as 50 paginated customer reviews or lengthy FAQ lists, are typically deferred to separate screens or loaded on demand.

If the mobile app consumes the same generic endpoint as the desktop web client:

  • Bandwidth Waste: Large payloads consume mobile data plans unnecessarily.
  • Resource Inefficiency: Parsing, deserializing, and holding surplus JSON structures in memory drains mobile battery life and causes client-side latency.
  • Sub-optimal UX: Viewport rendering is blocked or delayed while processing unneeded data.

2. Diverse Formats and Hardware Capabilities

Different clients operate under entirely distinct paradigms:

  • Voice Assistants (e.g., Alexa): Do not render visual elements. They require succinct text summaries or specialized SSML/speech structures to read aloud.
  • Mobile Features (e.g., AR/Camera/Sensors): Mobile apps may require integration with an Augmented Reality (AR) service to display 3D models of a product in real space—a capability irrelevant to most desktop web browsers.
  • Legacy B2B Systems / Banking Clients: Some upstream integrations only communicate via XML or specialized protocols, whereas internal backends operate on modern JSON/REST or gRPC.

3. The Pitfall of Backend Hacks

A naive attempt to fix this issue is parameterizing the core API:

GET /v1/product/12345?platform=mobile&omit_reviews=true&include_ar=true

This approach pollutes the core backend with conditional branching (if/else ladders) tied to front-end presentation concerns. It couples business logic to client-specific UX choices and complicates backend caching layers.


The Backend for Frontend (BFF) Pattern

The Backend for Frontend (BFF) pattern resolves this coupling by introducing dedicated, client-specific presentation layers between the user-facing interfaces and downstream services.

flowchart TD
    subgraph Clients
        WebClient[Desktop Web App]
        MobileClient[Mobile App]
        VoiceClient[Voice / Alexa]
    end

    subgraph BFF_Layer[BFF Presentation Layer]
        DesktopBFF[Desktop BFF]
        MobileBFF[Mobile BFF]
        VoiceBFF[Alexa / Voice BFF]
    end

    subgraph Core_Services[Core Backend Services]
        ProductSvc[Product Service]
        SellerSvc[Seller Service]
        ReviewSvc[Review Service]
        ARSvc[AR / 3D Asset Service]
    end

    WebClient --> DesktopBFF
    MobileClient --> MobileBFF
    VoiceClient --> VoiceBFF

    DesktopBFF --> ProductSvc
    DesktopBFF --> SellerSvc
    DesktopBFF --> ReviewSvc

    MobileBFF --> ProductSvc
    MobileBFF --> SellerSvc
    MobileBFF --> ARSvc

    VoiceBFF --> ProductSvc

How BFF Operates

  1. Client-Specific API Gateways: Each BFF service acts as a tailored API gateway designed specifically for a single client application or interface type.
  2. No Core Business Logic: A BFF does not manage canonical business logic, transactional workflows, or data persistence. It functions strictly as a presentation and orchestration layer.
  3. Presentation Responsibilities:
    • What to fetch: Knowing which downstream services are required for that specific client interface.
    • How to fetch: Concurrently calling downstream microservices or querying a monolith via internal protocols.
    • Transformation & Truncation: Stripping unneeded attributes, transforming payload formats (e.g., JSON to XML or SSML), and reshaping data to match the UI layout.

BFF with Monoliths vs. Microservices

  • With a Monolith: The backend exposes generic, fat APIs returning all possible data fields. Downstream caching is straightforward because queries are uniform. The BFF layer ingests this response, discards extraneous fields, and adapts the payload for mobile, web, or voice clients.
  • With Microservices: The BFF functions as an API Aggregator / Composer. When a mobile client requests product details, the Mobile BFF queries the Product Service, Seller Service, and AR Service in parallel, while skipping the Review Service entirely. It collates the responses and delivers an optimized payload in a single network hop for the mobile client.

Key Advantages of the BFF Pattern

1. Isolated, Client-Specific Interfaces

Frontend teams can modify their presentation requirements independently. If the mobile team decides to adjust the product screen layout or remove a widget, changes are made within the Mobile BFF without altering the Desktop BFF or modifying the core backend APIs.

2. Protocol and Network Stack Flexibility

The communication protocols used over external public networks do not need to match internal inter-service communication protocols:

  • Client to BFF: Can use HTTP/1.1, HTTP/2, WebSockets, or specialized payloads based on client constraints.
  • BFF to Microservices: Can leverage high-performance internal protocols such as gRPC over HTTP/2, binary serialization (Protocol Buffers), or keep-alive TCP connections to minimize latency across the internal network mesh.

3. Protocol Transformation for Legacy / Specialized Systems

If an external entity (e.g., an older banking integration) requires XML, a dedicated BFF can accept JSON from internal services, serialize it into XML, and handle communication without forcing downstream microservices to support obsolete standards.

4. Simplified Backend Caching

Because core services expose generic, un-parameterized interfaces without client-specific query hacks (?platform=mobile), their responses are uniform and predictable. This allows standard HTTP or reverse-proxy caching (e.g., Redis, Varnish) to operate with significantly higher cache hit ratios.

5. Client-Specific Security and Data Scrubbing

Security requirements often vary by client type. Mobile devices operating on untrusted public networks may require strict rate limiting, biometric token exchanges, or the removal of sensitive diagnostic fields. A BFF enforces these domain-specific controls and prevents private data fields from leaking to external clients.

6. Reduced Client-Side Network Round-Trips

Without a BFF or API composition layer, a client would need to make separate HTTP calls to ProductService, SellerService, and ReviewService directly over high-latency cellular connections. The BFF aggregates these requests within the datacenter or cloud VPC, requiring only one round trip from the user’s device.


Architectural Trade-offs and Disadvantages

AdvantageTrade-off / Architectural Risk
Request AggregationHigh Fan-out I/O Load: BFFs make numerous concurrent network calls, risking thread pool exhaustion if not built on an asynchronous, non-blocking I/O runtime (e.g., Go, Node.js, asynchronous Java/Netty).
Interface AutonomyCode Duplication: Desktop, mobile, and tablet BFFs often implement nearly identical service clients, models, and orchestration logic, leading to maintenance overhead across codebases.
Presentation DecouplingOperational Complexity: Introduces additional services that require automated CI/CD pipelines, container orchestration, monitoring, health checks, and alerting.
Tailored PayloadsAdded Network Hop: Inserting an intermediary layer adds network latency; for ultra-low-latency applications (e.g., high-frequency trading or real-time gaming), this extra hop may be unacceptable.

When to Introduce a BFF

The BFF pattern is a specialized architectural tool, not a default requirement for all systems. It should typically be adopted under two primary circumstances:

1. Significant Discrepancies Between Client Interfaces

If the data model and UI presentation diverge substantially between desktop web, native mobile apps, and other form factors (e.g., 80% of the desktop payload is omitted on mobile), a BFF prevents unnecessary bandwidth usage, reduces mobile battery drain, and improves response times.

2. Disparate Communication Formats and Protocols

When supporting clients that require specialized formatting—such as voice devices (Amazon Alexa), IoT integrations, or legacy enterprise clients expecting XML—a dedicated BFF isolates translation logic from core domain services.

When to Avoid BFF

  • Identical Client Interfaces: If your mobile application is a responsive web app or mirrors desktop content directly, a unified API Gateway is simpler and avoids unnecessary operational overhead.
  • Super-Low-Latency Systems: If every millisecond counts and intermediate hops degrade service-level objectives (SLOs), clients should interact with backend services via optimized direct connections or a minimal pass-through proxy.
Arpit Bhayani

Principal Engineer II at Razorpay - building Agent Studio, Ex-staff engg at GCP Memorystore & Dataproc, Creator of DiceDB, ex-Amazon Fast Data, ex-Director of Engg. SRE and Data Engineering at Unacademy. I spark engineering curiosity through my no-fluff engineering videos on YouTube and my courses