|
| 1 | +--- |
| 2 | +title: "Backends For Frontends Pattern in Java: Tailoring APIs to Client Needs" |
| 3 | +shortTitle: Backends For Frontends |
| 4 | +description: "Learn the Backends For Frontends (BFF) design pattern in Java. Understand how to give each client type its own dedicated backend service, with real-world examples, code, and diagrams." |
| 5 | +category: Architectural |
| 6 | +language: en |
| 7 | +tag: |
| 8 | + - API design |
| 9 | + - Architecture |
| 10 | + - Client-server |
| 11 | + - Decoupling |
| 12 | + - Microservices |
| 13 | +--- |
| 14 | + |
| 15 | +## Also known as |
| 16 | + |
| 17 | +* Backend For Frontend |
| 18 | +* BFF Pattern |
| 19 | + |
| 20 | +## Intent of Backends For Frontends Pattern |
| 21 | + |
| 22 | +Provide each client-side application (mobile, desktop, chatbot, and so on) with its own dedicated |
| 23 | +backend service, so every client gets an API shaped exactly for its own needs instead of sharing |
| 24 | +one general-purpose backend with every other client. |
| 25 | + |
| 26 | +## Detailed Explanation of Backends For Frontends Pattern with Real-World Examples |
| 27 | + |
| 28 | +Real-world example |
| 29 | + |
| 30 | +> Imagine a retail company whose mobile app, desktop back-office tool, and support chatbot all |
| 31 | +> need customer, cart, order and supplier data -- but a phone screen wants a short summary while |
| 32 | +> the back-office desktop tool wants full order and stock detail. Rather than exposing one shared |
| 33 | +> API that every client has to filter or over-fetch from, the company stands up a small BFF service |
| 34 | +> for the mobile clients and a separate BFF service for the intranet clients. Each BFF calls only |
| 35 | +> the downstream microservices its client needs and returns a payload shaped for that client. |
| 36 | +
|
| 37 | +In plain words |
| 38 | + |
| 39 | +> Give every kind of client its own tailor-made backend, instead of forcing all clients through one |
| 40 | +> one-size-fits-all API. |
| 41 | +
|
| 42 | +Sam Newman, who popularized the pattern, says |
| 43 | + |
| 44 | +> Create separate backend services to be consumed by specific frontend applications or interfaces. |
| 45 | +
|
| 46 | +## Architecture Diagram |
| 47 | + |
| 48 | +``` |
| 49 | +node mobile{ |
| 50 | + component iosapp as "ios app" |
| 51 | + component androidapp as "android app" |
| 52 | +} |
| 53 | +node intranet{ |
| 54 | + component desktop as "desktop app" |
| 55 | + component chatbot |
| 56 | +} |
| 57 | +component bff as "BFF server"{ |
| 58 | + component iosbff as "ios BFF" |
| 59 | + component androidbff as "android BFF" |
| 60 | + component chatbotbff as "chatbot BFF" |
| 61 | + component desktopbff as "desktop BFF" |
| 62 | +} |
| 63 | +node intranetserv as "intranet services server"{ |
| 64 | + component ss as "supplier service API" |
| 65 | +} |
| 66 | +cloud onlypublic as "public cloud"{ |
| 67 | + component cas as "customer authentication service API" |
| 68 | + component cs as "cart service API" |
| 69 | +} |
| 70 | +cloud cloudserv as "managed cloud"{ |
| 71 | + component os as "order service API" |
| 72 | +} |
| 73 | +iosapp -- iosbff |
| 74 | +androidapp -- androidbff |
| 75 | +chatbot -- chatbotbff |
| 76 | +desktop -- desktopbff |
| 77 | +iosbff -- cas |
| 78 | +androidbff -- cas |
| 79 | +iosbff -- cs |
| 80 | +androidbff -- cs |
| 81 | +iosbff -- os |
| 82 | +androidbff -- os |
| 83 | +chatbotbff -- os |
| 84 | +desktopbff -- os |
| 85 | +chatbotbff -- ss |
| 86 | +desktopbff -- ss |
| 87 | +``` |
| 88 | + |
| 89 | +This example implements a simplified version of the diagram above with two client-facing BFFs |
| 90 | +instead of four, to keep the demo focused: a **Mobile BFF** standing in for the ios/android BFFs, |
| 91 | +and a **Desktop BFF** standing in for the desktop/chatbot BFFs. Both call into the same shared |
| 92 | +downstream services (`AuthService`, `OrderService`), while `CartService` is only used by the |
| 93 | +Mobile BFF and `SupplierService` is only reachable from the Desktop BFF, matching the fan-out |
| 94 | +shown in the diagram. |
| 95 | + |
| 96 | +## Class Diagram |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | +## When to Use the Backends For Frontends Pattern in Java |
| 101 | + |
| 102 | +* Different client types (mobile, web, desktop, voice/chat) need meaningfully different shapes, |
| 103 | + granularity, or aggregation of the same underlying data. |
| 104 | +* A single shared API has grown a large number of client-specific conditional branches, optional |
| 105 | + fields, or query parameters to accommodate every consumer. |
| 106 | +* Different client teams need to iterate on their own API independently without coordinating |
| 107 | + changes through one shared backend team. |
| 108 | +* Some clients (e.g. mobile) need aggressively trimmed payloads for bandwidth/latency reasons, |
| 109 | + while others (e.g. an internal desktop tool) need much richer data. |
| 110 | + |
| 111 | +## Benefits and Trade-offs of Backends For Frontends Pattern |
| 112 | + |
| 113 | +Benefits: |
| 114 | + |
| 115 | +* Each client gets an API optimized for its own needs, improving performance and simplicity on |
| 116 | + the client side. |
| 117 | +* Client teams can evolve their BFF independently, reducing cross-team coordination. |
| 118 | +* Downstream microservices stay generic and reusable; client-specific logic lives in the BFF |
| 119 | + layer instead of leaking into shared services. |
| 120 | + |
| 121 | +Trade-offs: |
| 122 | + |
| 123 | +* Introduces additional services to build, deploy, and operate. |
| 124 | +* Logic that is genuinely shared across clients can end up duplicated across BFFs if not |
| 125 | + carefully factored out. |
| 126 | +* Adds an extra network hop between the client and the downstream services. |
| 127 | + |
| 128 | +## How to Implement Backends For Frontends Pattern in Java |
| 129 | + |
| 130 | +1. Identify the distinct client types that need meaningfully different data shapes. |
| 131 | +2. Define the downstream services each client's data actually depends on (`AuthService`, |
| 132 | + `CartService`, `OrderService`, `SupplierService` in this example). |
| 133 | +3. Create one BFF per client type, implementing a shared `ClientBff<T>` contract, where each BFF |
| 134 | + only depends on the downstream services its client needs. |
| 135 | +4. Have each BFF aggregate and reshape the downstream data into a response DTO tailored to its |
| 136 | + client (`MobileDashboardResponse`, `DesktopDashboardResponse`). |
| 137 | +5. Wire the client applications to call their own BFF rather than the downstream services |
| 138 | + directly. |
| 139 | + |
| 140 | +## Source Code |
| 141 | + |
| 142 | +* [Pattern: Backends For Frontends](https://samnewman.io/patterns/architectural/bff/) by Sam Newman |
| 143 | +* [Microservices Patterns: With examples in Java](https://www.amazon.com/Microservices-Patterns-examples-Chris-Richardson/dp/1617294543) by Chris Richardson |
| 144 | + |
| 145 | +## References and Credits |
| 146 | + |
| 147 | +* [Building Microservices](https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/) by Sam Newman |
| 148 | +* [Pattern: Backend for frontend (microservices.io)](https://microservices.io/patterns/apigateway.html) |
0 commit comments