The Backends for Frontends (BFF) Pattern
Many textbooks assume that your frontend will just call a single, beautiful, and secure API, but in the real-world this is rarely the case…
For example, imagine a bank that offers both banking and insurance to its customers. The bank has acquired the insurance business, which already had an insurance solution. The customer master data is stored in a CRM system. So if we were tasked with developing a customer self-service portal for the bank, the portal would need to call three different systems (CRM/Bank/Insurance), with three different protocols, and three different security schemes, just to get a basic overview of a customer’s engagement with the bank.
A common way to overcome this imperfect setup is to create a new backend in front of the real backend(s) and then design the perfect API for the frontend.
This is known as the Backends for Frontends (BFF) pattern and an example (using our imaginary bank) is shown below:
The Web BFF in the diagram above can expose a simple GET /customers/{id}
REST operation that our frontend can call instead of dealing with the complexity of calling and integrating three different systems.
Beside respecting the separation of concerns principle, by separating our presentation logic from our integration logic, we get many more benefits from using the BFF:
- Call the backends in parallel: We can call the backends in parallel and perhaps respond faster to the end user.
- Filter the responses: We can remove internal or sensitive data, such as an unwanted customer flag, or unnecessary data that just adds complexity to the frontend and drains battery power when parsing on mobile devices.
- Transform the responses: We can transform the responses to the frontend into something more usable, such as translating internal codes to something more descriptive. For example, a code in a job field can be translated from
SH_CLERK
toShipping Clerk
. - Enhanced security: We can add extra security in the BFF, such as OAuth2, to protect the unsecure backend solutions, and we can implement a single sign on, so the frontend doesn’t need to deal with different authentication methods in different backend systems.
- Handle different protocols: The BFF can call FTP, SOAP, REST, GraphQL, and other types of services, but still use a single protocol when interacting with the client.
- Encapsulate advanced business logic: Issuing a new insurance policy may be a complex operation that requires multiple service calls, but this can be simplified for the clients into a single end point with only the absolute minimum data in a flat structure.
- Caching across clients: Some of backends may be slow so caching across different clients may be an effective way to deliver acceptable response times to the end users. Moreover, if we need to call usage-based external APIs, it may also be worth caching those responses across clients to reduce the cost.
- Protect the client from changes to the backend: Changes in the backends APIs need not to result in changes in the UI, the changes can be handled in the BFF.
- It’s still just code: A BFF doesn’t involve canonical data models, ESBs, or other old-school integration patterns that are complex and time consuming to deal with; it’s just plain code. Moreover, a change in the BFF will not affect other systems, like with an ESB, so it is better aligned with DevOps and microservice thinking.
The main drawback of the BFF pattern is that, at least in the beginning, it can seem like extra work for the frontend team (which should be the ones developing and owning the BFF) but it usually pays back if the underlying backends are non-trivial. Remember that there are no technical restrictions to what language / framework we can use for the BFF; if the frontend team is skilled in JavaScript, they may be more comfortable with writing the BFF in Node.js and that’s perfectly fine.
Having frontend team to develop BFF might be quite a challenge:
1. that implies such team should be/become full stack developers.
2. diving into specific business domain (=understanding underlying backends) might be difficult and time consuming.
Not every developer is willing to get into the above.
I’d expect a new team to be formed for building BFF, where each underlying backend system and frontend has a representative with required domain knowledge.
I know dedicating resources is difficult at times, but in theory this should work better, shouldn’t it?
Good comments! Yes, the frontend team will need a fullstack or backend engineer who can develop the BFF. This doesn’t necessarily means that everybody on the frontend team needs to be fullstack developers.
The task of understanding the backend APIs that the frontend needs to call, I see as the same whether the frontend team uses a BFF or not.
/Kenneth