Backend-For-Frontend using GraphQL under Microservices

Mina Ayoub
tajawal
Published in
7 min readMay 15, 2018

Microservices are an architectural style, in which the analysis and modeling of specific business areas, complex applications are decomposed into a group of services that are small and specific, have a low degree of coupling. Each microservice is a small, independent and deployable application.

This concept of microservice architecture is similar to the concept of separating the frontend and backend. The frontend application controls all of its own UI-level logic, while the business logic is accomplished through API calls to the relevant microservice. After the continuous growth of frontend single page application frameworks, and the spread of mobile apps, whether it is a Mobile Native development or a Hybrid application development, so frontend and backend separation has made Web and Mobile applications become clients. The client only needs to query and modify the resources through the API.

The following figures shows the main difference between the absence of BFF and the addition of BFF on the front and back ends.

1. Traditional frontend and backend separation application

In the traditional frontend and backend design, usually the Mobile App or Website directly accesses the backend service, the backend microservices call each other, and then return the final result to the frontend client. For clients (especially mobile), too many HTTP requests are expensive. Therefore, in order to minimize the number of requests, the frontend generally tends to obtain associated data through a single API. It means that sometimes the backend will do some UI-related logic processing to meet the needs of the client .

2. BFF’s frontend and backend architecture

The biggest difference in BFF’s frontend and backend architectures is that the frontend (Mobile, Web) no longer directly accesses the backend microservices, but rather accesses it through the BFF layer. And each client will have a BFF service. With BFF, there are fewer mutual calls between microservices. This is because some UI logic is processed at the BFF level.

BFF and API Gateway

From the above understanding of BFF, since BFF is a middle-tier service accessed by frontend and backend, what is the difference between BFF and API Gateway? Let’s first look at the common implementation of API Gateway. (The API Gateway may be designed in many ways. Here are just three examples.)

1. API Gateway provides the same API for all clients

For example: /api/accounts. In this case, API Gateway does not distinguish between client types, as shown below:

2. API Gateway provides separate APIs for each client

For example: /services/mobile/api/accounts and /services/web/api/accounts. The API Gateway determines which client it comes from, based on different APIs, and then processes them separately to return the resources required by different clients.

3. Multiple API Gateways provide separate APIs for each client

BFF is actually considered like this implementation mode of API Gateway.

GraphQL and REST

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

What are the similarities and differences between GraphQL and REST? We can understand it by the following example:

REST can be accessed through the following way:

Request:

GET http://127.0.0.1/api/accounts

Response:

[
{
"id": 88,
"name": "Mena Meseha",
"photo": "http://bucket.s3.amazonaws.com/photo.jpg"
},
...
]

For the same request if accessed with GraphQL, the process is as follows:

Request:

POST http://127.0.0.1/graphql

Body:

query {accounts { id, name, photo } }

Response:

{
"data": {
"accounts": [
{
"id": 88,
"name": "Mena Meseha",
"photo": "http://bucket.s3.amazonaws.com/photo.jpg"
},
...
]
}
}

Compared to the REST style, GraphQL has the following features:

1. On demand data model definition

For example, for the above /accounts access, if the client is only interested in account.id and account.name. So client only need to pass account {id \n name}to query. The model is defined in the background. The client only needs to obtain the data it cares about.

2. Get many resources in a single request

For example, you may need to obtain account.friends and account.friends.address, In fact, this query need to get the data from 3 different resources which are account, friends and address. In REST mode, the account data may needs to be sent again to another API to get the friends and address info. GraphQL can query for nested levels of data so it greatly reduces the number of client requests and allows the client to obtain all the required data through a single API as the following query:

{
account(id:88) { // 1st Level
name,
friends { // 2nd Level
name,
address { // 3rd Level
country,
city
}
}
}
}

GraphQL vs REST

For the comparison between GraphQL and REST, there are mainly the following differences:

1. Data Acquisition: REST lacks scalability and GraphQL can be accessed on demand. The payload can be extended when the GraphQL API is called.

2. API calls: REST’s operation for each resource is an endpoint, and GraphQL only needs a single endpoint, but the post body is not the same.

3. Complex data requests: REST requires multiple calls for nested complex data, GraphQL calls once, reducing network overhead.

4. Error code processing: REST can accurately return HTTP error code, GraphQL returns 200 uniformly, and wraps error information.

5. Version number: REST is implemented via v1/v2, and GraphQL is implemented through the Schema extension.

Microservices + GraphQL + BFF Practice

I recommend to use express-graphql to build the BFF side of the project and then deploy it through Docker, and between the BFF and the microservices backend, there is service registration and discovery are performed through Consul.

Sample Technical Architecture for Microservices + GraphQL + BFF
BFF Technology Stack

Authentication and Authorization

Authentication and authorization are other issue that need to be considered when using GraphQL. Do we process them before or after the GraphQL parsing process?

To answer this question, you can think of GraphQL as a DSL (Domain Specific Language) on top of your own backend data acquisition logic. We just need to think of it as an intermediate layer that can be placed between the client and our actual data service (or multiple services).

Then consider authentication and authorization as another layer. GraphQL is not useful in the actual implementation of authentication or authorization logic because it does not mean it. However, if we want to place these layers behind GraphQL, we can use GraphQL to pass the access token between the client and Auth API. This is very similar to the way we authenticate and authorize via the RESTful API.

3. GraphQL + BFF Practices

Through the following aspects, you can think about some of the better qualities of GraphQL-based BFF:

GraphQL and BFF’s focus on business points

From a business point of view, the property manager (PM App) is concerned with property, because the property manager manages a group of houses, so it is necessary to know all the house profiles, and for each house need to know whether there is a corresponding maintenance application. Therefore, PM App BFF data structure is defined, maintemamceRequests is property sub-attribute.

With similar data, the house maintenance supplier (Supplier App) is concerned with maintenance request (maintenance work order), so in the data obtained by the Supplier App, our main body is maintenanceRequest.

So because there are different usage scenarios, different clients have different concerns for the same data. From this perspective, the data structure defined in the BFF is what the client really cares about. BFF is born for the client and is part of the client. It should be noted that the "business focus" does not mean that the BFF will handle all the business logic. The business logic should still be taken care of by the micro service. The BFF is concerned with what the client needs.

GraphQL support for versioning

Figure (1) -> Figure (2) -> Figure (3)

Assume BFF end has been released into the production environment. Now we need to change the structure of Figure (1) to the structure of Figure (2), but in order not to affect the API access of the old users, our BFF API must be compatible at this time. If REST, we may update the API version. But in BFF, we can use the structure of Figure (3) for forward compatibility. At this time, the old APP uses the data structure of the yellow area, while the new APP uses the structure defined by the blue area.

Conclusion

Building a BFF based on GraphQL under microservices is not a silver bullet. It is not necessarily suitable for all projects. For example, after you use GraphQL, you may have to face multiple query performance issues, but this does not prevent it from becoming a good attempt. You do see that Facebook has already used GraphQL, and that Github has also opened GraphQL’s API. This article only serves as an introduction to the idea. I hope that there will be more sharing about the use of BFF in the community.

--

--

Mina Ayoub
tajawal

I'm enthusiastic about being part of something greater than myself and learning from more experienced people every time I meet them.