BFF Pattern: Solving integration issues
The microservices approach is a worldwide known and accepted concept, this concept, as you may know, divides software responsibilities (modules) into more than one layer (or service). And every service has its environment that it needs to maintain, and it is responsible for, of course.
Accessing and navigating through the Amazon website, for example, you are probably touching a bunch of Amazon microservices but for you, the experience is as if you are handling just one thing. Deep diving a little bit at the technical approach, how does your frontend know which service is supposed to retrieve certain information? Because, as it is separated microservice it probably has a different URL to access it. Is the frontend supposed to be responsible for knowing the different URLs used for our backend applications? An API Gateway could be used to resolve it but, if we need information from more than one service? Should we perform an HTTP request for every service to group all the information we need? Don’t sound like a good approach, right?
First touch
Because of those situations and some others, you could use the BFF pattern to solve them. But what is the BFF pattern? BFF stands for Backend for Frontend, which means that you are going to have a specific backend service responsible for sending information to your respective frontend. Not necessarily just for your frontend applications but for your channels (a channel is something that brings information to the user, such as web applications, mobile apps, reports, etc.). In this way, you are going to be able to have a dedicated backend that is going to deal with all the needs of your frontend application would have.
The following diagram shows a little how this pattern works.
As you can see, the BFF application is responsible for grabbing and grouping all information necessary for a specific endpoint that the frontend/channel consumes. Not only that but also, it can format the data as it is expected to be sent. So now, the frontend application will just integrate with a single application which is going to retrieve data from services as much as it needs, being transparent for the frontend application.
Problems when a single BFF application is used.
In one of my past roles in an amazing company, we used to have this pattern to deal with all the data we needed to send to our channel. In that situation, we had a couple of backend services for the same channel (mobile app), as our teams and our delivery speed grew, we started to face an issue, a lot of conflicts when committing code to the BFF application. This application started to be heavy, which meant a longer time to deploy, harder to maintain, different teams working on that, and a loss of cohesion.
Another problem you can face using the single BFF approach is having conflicts about data formatting or even data grouping depending on the channel consuming the data. For both situations, we can solve in the same way.
A solution for that, and it is what we did at that moment at the company I mentioned earlier was, that we have created a second BFF application using a criterion of division. The point is, that you can have more than one BFF application for your solution. To have the most cohesive architecture using the BFF pattern is to have a BFF application for each channel or module your solution has. Using the same scenario as before but now, with a BFF application for each channel, the diagram would be like the following.
As you can see, with that approach, every BFF application is going to have specific endpoints, formatting, and models based on its usage from the specific channel. As the BFF application now is specific to a channel, the team responsible for the channel can now maintain its BFF application, having as many deliveries as it needs, as often as it needs too, and don’t depend on any other team anymore as well.
BFF + Legacy applications
On top of it, there is one other good usage for the BFF approach, which is the usage of a BFF application to grab information from a legacy software where sometimes, because of lack of technical stuff or people/companies are afraid to modify it (here I can use as an example the dinos application from banks), it is not able to have a new frontend application. But, after you plug a BFF application a brand-new high-tech with the newest patterns frontend application can read, format, group, modify, and add new data to the legacy application independently of the stack used on the legacy application or even if it doesn’t receive changes anymore. Instead of having services as we saw previously, in this scenario, we are going to have a legacy application behind the scenes and the BFF approach is going to work in the same way though.
We were able to see a couple of usages for the BFF pattern in this article, which can bring a lot of versatility to your new or legacy applications. I am one of the supporters of this approach, from my point of view it brings more pros than cons. But we must keep in mind that every new BFF application is an entire application, which means that, there are more pipelines to create, more repositories to maintain, more deploys to do, more monitorability, more alerts, and so on. On the other hand, having a good and automated CI/CD process will easily manage it for you for sure and you are going to have a good approach for your solution.
I hope you enjoyed it! Any questions or comments, please feel free to contact me. See ya in the next article! Bye!