Best Architecture for Your Next Project, Framework Doesn’t Matter! 🎉
Published: 2024-07-16 14:08:14

### Table of Contents
1. [How Simple Engineering Works](#how-simple-engineering-works)
2. [What Happens When We Decide to Scale or Mature the Project](#what-happens-when-we-decide-to-scale-or-mature-the-project)
3. [What the Heck is BFF?](#what-the-heck-is-bff)
4. [How BFF Helps with Scaling the Project](#how-bff-helps-with-scaling-the-project)
5. [Using BFF in the Real World](#using-bff-in-the-real-world)
6. [Benefits of Using BFF](#benefits-of-using-bff)

### How Simple Engineering Works

![Simple Two tier Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e40vw5up7jqzt9gsn7i9.png)

1. **Frontend** makes a call to **Backend APIs**.
2. **Backend APIs** process the request and send a response back.
3. The **Frontend** renders the response accordingly.

This works pretty well when you're building an MVP.

![MVP Success](https://media.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif)

### What Happens When We Decide to Scale or Mature the Project 🚀

- Backend APIs start following the **[Single Responsibility Principle](https://www.geeksforgeeks.org/single-responsibility-in-solid-design-principle/)**.
- APIs can be grouped together in services, or microservices can be introduced.
- Client-side code becomes more complex.
- Frequent changes in request-response structures become common between frontend and backend.
- More data gets loaded into the frontend.
- When addressing multiple client types (e.g., web and mobile), APIs become more bloated.
- Multiple concurrent requests go to the backend to address page UI demands.

This can become as overwhelming as my girlfriend’s never-ending list of demands. So, to help, one of my senior team-mates introduced me to the concept of **BFF**. Whether in real life or code, BFFs always have your back.

![Help](https://media.giphy.com/media/gw3MYmhxEv8T52ow/giphy.gif)

### What the Heck is BFF? 🤔

A **Backend for Frontend (BFF)** is a mediator that tailors backend services to the specific needs of different clients. Think of it as the best friend who filters all the chaos and serves you only what you need. The frontend calls a BFF server API endpoint, and then the BFF does the heavy lifting, calling all the backend services required.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iuv68d26gev4bxfhm6qj.png)


![BFF](https://media.giphy.com/media/KD2MpVnA4tmGF6nQMx/giphy.gif)

### How BFF Helps with Scaling the Project 🛠️

**Why maintain another mediator server, BFF, in this case? Why not stick to the old and proven two-tier architecture?**

Because now we care about user experience! We’re no longer an MVP and can’t be running around like headless chickens.

![Chicken](https://media.giphy.com/media/yVGyltTPq1EjHRLHZh/giphy.gif)

Our backend APIs follow the Single Responsibility Principle, but our UI needs a lot of data, which means making calls to many backend APIs. The catch is that most browsers only allow 6 concurrent requests per domain. You can read more on this limitation over this [Stackoverflow thread](https://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser). So, if you have a dashboard showing data from 3-4 services, each with many APIs, the browser can only handle 6 at a time. Once those are done, it processes the next 6. And this is without counting the initial script loading!

![Maximum connections allowed per domain in browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6j8o3ndh3vzhn2hra5u0.png)


**Enter BFF:** The client makes a single call to the BFF, and the BFF makes all the calls to all the services without the parallel connection limitations. Problem solved!

![Problem Solved](https://media.giphy.com/media/Ztzt8zhmmpVPUiSNMX/giphy.gif)

But what if the number of concurrent connections wasn’t the issue? Should you still use the BFF pattern? My answer is a resounding yes!

Imagine you have a dashboard showing data from 3-4 services. You’ll likely be doing some client-specific computation, adaptation, or transformation of data before showing it to the end user. For small chunks, doing this on the client works well. But as the data transformations get more complex, it becomes a bottleneck for user experience. JavaScript is single-threaded, and the UI starts to feel laggy or jittery because the browser is busy transforming data instead of serving the UI.

**A simple fix:** Move all the presentation, adaptation, or transformation logic to the BFF. This way, the client's browser is free to focus on rendering content. Plus, the BFF adapts to any changes in backend API response structures, so the frontend sees a consistent response structure.

**But what about the BFF API becoming too generalized or bloated? Doesn’t it need to follow the Single Responsibility Principle too?**

The single responsibility principle is a bit different for BFF. A single BFF server endpoint should ideally load or update data related to a single UI page. Different client types (like mobile and web) can have their own BFF servers. Each BFF server sends back a thin, tailored response to the client. Mobile has less real estate than web, so the BFF server can easily trim the response.

So, while BFF server APIs might seem bloated and generalized compared to backend service APIs, they still follow the Single Responsibility Principle.

![Backend for frontend (BFF) Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3yts5zpop2s6p428mbm.png)


### Using BFF in the Real World 🌍

**Setting Up and Exploring an Open-Source Project**

1. **Project Setup**:
   - Follow the steps in the [project's README](https://github.com/middlewarehq/middleware) to set up the project.
   - Once the setup is complete and the server is running, visit [https://localhost:3000/dora-metrics](https://localhost:3000/dora-metrics).

2. **Open Network Tab**:
   - Open your browser's developer tools (press `F12` or `Ctrl+Shift+I`).
   - Go to the 'Network' tab to monitor API calls.

3. **Observe API Calls**:
   - Notice that the page loads most of its data from the response of `/internal/team/${team_id}/dora_metrics`.
   - This is a BFF API endpoint responsible for loading all the required data for the `/dora-metrics` route page.

![Middleware dora metrics dashboard api calls](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26cenl08oilka31sgje4.png)



4. **Examine the Codebase**:
   - Navigate to the code for the `/internal/team/[team_id]/dora_metrics` module.
   - Observe the concurrent invocation of multiple backend services using `Promise.all`.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ymsvdqpze1ea48qr97b.png)


5. **Understand the Benefits**:
   - Under the hood, we are calling 5 different backend services and making a total of 18 API calls.
   - If the same number of calls were made from the frontend, it could take 3x more time than using the BFF approach.

Following these steps will help you understand how the BFF pattern is implemented in a real-world project and appreciate the benefits it brings in terms of performance and user experience.

### Benefits of Using BFF 🌟

1. **Improved User Experience**: By offloading complex data transformations and aggregations to the BFF, the client's browser can focus on rendering, resulting in a smoother UI experience.
2. **Optimized API Calls**: The BFF can aggregate multiple backend API calls into a single call, reducing the number of requests the client needs to make.
3. **Tailored Responses**: Different clients (web, mobile) can have their specific BFF servers, ensuring that each client receives data tailored to their needs.
4. **Adaptability**: The BFF can adapt to changes in backend API structures, providing a consistent interface to the frontend.

In conclusion, adopting the BFF pattern can significantly improve the scalability, maintainability, and user experience of your application as it evolves from an MVP to a mature product. And remember, whether in code or life, a good BFF always has your back!

![BFF Saves the Day](https://media.giphy.com/media/3o7aCTfyhYawdOXcFW/giphy.gif)

If you found this article helpful and enjoyed exploring the BFF pattern, please consider starring [middleware repository](https://github.com/middlewarehq/middleware). Your support helps us continue improving and sharing valuable content with the community. Thank you!
{% embed https://github.com/middlewarehq/middleware %}