BFF Pattern — Dos and Don’ts. The right way to implement…
By: Viduni Wickramarachchi
Tags: Nodejs, Backends For Frontends, Backend Development, JavaScript, Front End Development

1. Modality

Your application may have two or more microservices (e.g., Customer, User, Order, etc.) and a few frontends serving different purposes. When I say a few frontends, it does not only mean a public-facing interface. For example, an application with varying requirements for frontend could be as follows:

Desktop Application

Mobile Application

Third-party Services/APIs

How do we structure our BFF to serve all these?

❌ — Do NOT use one BFF for all these requirements.

✅ — Use Multiple BFFs for each requirement.

If we take each of these frontend requirements, each one is unique. So, for example, the scalability requirement of the API could be way higher if more integrations are there with your application.

Therefore, if we use multiple BFFs for Desktop, Mobile, and API respectively, we can optimize each BFF based on the different requirements of these clients. Further, having separate BFF would make the application more fault-proof and cost-effective.

2. One Experience — One BFF

Maintaining multiple BFFs can be a cumbersome task. However, rather than a single BFF serving multiple purposes, multiple BFFs serving a more optimized purpose make more sense. What we discussed in the previous point can be enhanced further to provide a single experience per BFF.

❌ — Do NOT use one BFF for multiple experiences.

✅ — Use Multiple BFFs per experience optimizing the BFF best to serve the experience.

For example, let’s say your application has an iOS application and an Android application. If both of these provide the same or almost similar experiences, having one BFF would serve the purpose. However, if the iOS application and Android application serve different experiences, need different formats, handle requests in different manners, having two BFFs for them would be the best way to go.

3. Multiple Downstream Services

In an application with a few microservices, the BFF wouldn’t have to make a lot of calls in order to get some information to be displayed in the frontend.

However, let’s say we have a large e-commerce application with a large scope of functionality. For example, we have to extract information to show the favorite products of a customer with their stock levels and prices. In our application, the favorite products and relevant logic is managed by the Wishlist service, stock levels are managed by the Inventory service and the prices should be extracted from the Product service.

However, there could be scenarios where one or some of these services are not available at the time of the request. If the Wishlist service is not available, the request can be fulfilled. However, let’s say the Inventory service is not available but the other two services are available. If the frontend is designed in a way where it could accept partial information to be shown, the BFF should be designed in a way where partial information will be processed.

❌ — Do NOT fail the entire request from the frontend if partial data isn’t available due to service failures.

✅ — Process the request partially if sufficient information is extracted from the microservices and if it can be displayed correctly in the frontend

4. Responsibility

The BFF should be an interface between the frontend/client applications and the microservices. However, there is a limit to what the BFF can handle. Just because we have a BFF in our application, we shouldn’t hand over all the responsibility to it. For example, any sensitive processing such as authentication and authorization should not be handled solely by the BFF. There should be a separate microservice that handles such critical processing.

❌ — Do NOT expect the BFF to handle all the responsibility. Do NOT over-rely on the BFF.

✅ — Keep the BFF as a thin layer that processes requests to be sent to the microservices, an interface that bridges microservices and the client applications, and also a thin layer that can format and process data if and when necessary to optimize the data for the frontend.

5. Team Ownership

At first glance, it seems like having a BFF would increase development time as it is another layer that we need to manage. While this is a valid concern, the benefits of having a BFF outweigh the concerns of development time. In order to make sure that we don’t increase development time drastically and make the application less manageable, the best way to manage a BFF is by giving that responsibility to the associated frontend team.

❌ — Do NOT have separate teams to manage BFFs.

✅ — Allow the respective frontend team to manage their respective BFFs.

This has a few advantages.

Frontend teams do not have to wait till another team completes BFF functionality.

The frontend team knows best the type and format of data required for the frontend to provide an optimized user experience.

Development time will be reduced.

You can use Bit to build all your components and modules (for the backend and frontend) in the same workspace by setting a different development environment for different components.

Each component will be developed and versioned independently (using Bit). These independent components can then be pushed to a single remote hosting, a ‘remote scope’, that grants the right permission levels to all members of that team.