BFF Dilemma

The software industry is always becoming more specialized. We have backend engineers, frontend engineers, edge engineers, cloud/DevOps engineers and I'm sure we will have more specialization in the future. With specialization and growth on systems, we end up having more layers or places that we can put software. Microservices often end up making a huge proliferation of services at the backend(check out Uber case for that).  There are so many places that you can "put" your software but one particular place that is growing a lot is the BFF(Backend for Frontend) place. Often we have different stacks for backend and frontend. Frontend often is on JavaScript or TypeScript. Backend is often in Java, .NET or Go. So the first dilemma is, is BFF a frontend thing or a backend thing? IMHO it's a frontend thing where frontend means consumer. So how different BFF is from a driver or client? Well if you look into drivers and clients they often dont have network logic like routing, discoverability, circuit breaking where BFFs often dont. There is nothing preventing you put that logic on the BFF which really raises the question of how different BFF is from drivers/clients. Definitely, there is an overlap with Drivers/Clients/BFFs and even Services. 

BFFs the Benefits

Let's say you have a big app or multiple apps with multiple platforms like IoS and Android. Let's say you also have multiple sites or web application, it will be common to have a design system where you company want to have a standard view of the brand experience(colors, fonts, tons, etc...). It's important to leverage components, if you are working with React thats even easier and natural. However, another dilemma that often happens is, should I make a design system component, or thats something just for the app? Well, that is a couple of factors that could help you to figure it out. 

* How many apps/sites will have that feature/component? 

* How often that behavior it's likely to change? 

* How complex is to make the component? 

Even if you decide to go one route vs another route you can always refactor. So refactorings are cheap others are not, so as you grow you need to keep asking these questions. But regardless of what kind of component you end up doing or not doing you have benefits on the BFFs like:

* Caching 

* Sever Side Rendering - Which also can be done in a generic way. 

* Centralize and Re-use UI Logic (not business logic)

However, sometimes the UI Logic can easily be seen as business logic, in some sense microservices are making this much worst them it is.

Microservices are making BFFs Fat

I remember first waves of SOA where the default was to write code on the service, the services end up being FAT and with stuff that supposes not to be there. However, I also remember we having Aggregation Services, which were services that call other services and that was like the Gateway Uber is talking about on the re-discover of DDD post on DOMA. 

Right now we have a different default, meaning, do not put stuff on the service, they need to be micro. The consequence is that complexity is pulled upwards. Complexity needs to live somewhere and microservices right now tend to be super simple and small however all the orchestration/choreography is being done by the BFFs which are getting more fat and complex. 

It's a Governance Problem

IMHO we need Services, not Microservices. Services should be a bit more FAT. It's fine if the BFF is also FAT as long as it makes sense. So we are talking about a governance problem, that we need to answer some of the following questions:

 * Where we put our code? (BFF, Aggregator Service / Gateway, Service)? 

 * Are the decisions we made on the past still make sense? 

 * Are we running joint Event-Storming exercises to figure out boundaries? 

 * How do we version APIs? Do we provide forward and backward compatibility? for how long?

 * How we expose APIs? HTTP/2, gRPC? 

 *How own what component? 

 *How we test things properly? Are we having WASTE on our tests? 

 *How we coordinate cross-team efforts? 

 *Do we create a lib instead? Sidecar? 

It's also a management problem

There are lots of options to manage this kind of cross-coordination. Do we have a big team as just have a big kanban to handle it? Do we have a chapters/guild(Spotify) to take care of that? Do we have a small pizza team(amazon) to execute the changes? Amazon's way relies on autonomy as a business construct and lean way it kind of makes a lot of sense because of the dependencies and lack of business autonomy you might end up here. When I say business autonomy I dont mean if you company has a cool culture and people are allowed to experiment and do stuff. I mean autonomy is a business construct, so you need to be able to generate results by ourself otherwise you always will have dependencies and you might be better served by the lean model. 

Guidelines and Reflection Over Rules

Rules should be avoided because like any Design and Architecture matter we need to apply judgment. There is no one size fits all, so thats why rules are complicated. Judgment might be right or wrong or it might be right for a period of time and them things change and it's not valid anymore. For all those reasons we need continuous reflection, via big long retrospectives and working groups. Dilemmas are not bad, they are good actually it forces us to think which is our job. If we are not thinking a lot we might be following things we dont understand and creating debt and problems for the future :-) 

Guidelines are awesome because they are not hard rules, you should have very few hard rules in a sense of design and architecture. Guidelines are educative and teach people how to approach problems. One thing I use a lot with Guidelines is Principles, I love principles they are great and I few the industry needs to use them more. 

Cheers,

Diego Pacheco


Popular posts from this blog

Kafka Streams with Java 15

Rust and Java Interoperability

HMAC in Java