REST APIs are the defacto standard for any client-server or service to service communication. However, diverse clients bring their own requirements resulting in REST-ish APIs that either over-fetch or under-fetch data. This results in chatty I/O between frontend and backend. Each page render would require calls to multiple services, 3rd party APIs, and so on.
Enter the BFF design pattern and GraphQL.
It helps solve some of these problems by aggregating multiple backend services/sources and providing one interface to each client to fetch only the data it needs, while GraphQL makes it easy to build BFFs. It allows clients to define what they need and get exactly, and only, that. It also allows the server to define the data it can provide as a DSL.
That said, GraphQL and BFFs are no one-size-fits-all solution. We would always need to work backward from the requirement and fit the technology to it.
In this blog, I explore the typical challenges with REST APIs, types of requirements that benefit from a Backend-For-Frontend (BFF) design pattern, and how GraphQL helps build a BFF.
When we have REST APIs why do we need anything else?
Most API frameworks allow clients to call an API endpoint, pass query parameters, and receive a response that the client needs to process, based on their needs.
The shape of the REST API response is always defined by the server.
REST-ish APIs define the following:
- API end-point
- HTTP verb
- Query parameters
For example, I have a website displaying the data on the weather of Mars – particularly the information on pressure. NASA has a public API for this.
The response contains the HTTP status code and the JSON response that is defined by the server.
The client does not control the shape of the response. This introduces a few problems.
- Over-fetching: In this case, I wanted to just fetch and display the pressure data. However, the response, as you see, has multiple other data points per the predefined server response.
- The response payload here is 25 times bigger than the one with just the data point I am interested in
- The client application does not have any control over what it receives
- This is the over-fetching of data
- This is especially problematic when it comes to mobile applications. The higher payload will result in increased network traffic, slower page load times, and increased load on the server
- Under-fetching: Assume I also want to display the image of the Curiosity rover on the same page, along with the weather data
- In this case, I have to call another API. https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEMO_KEY
- The client application will have to make two requests to the server
- Each network call even with minimal latency is a costly operation
As your application evolves, your API call pattern will begin to resemble something like this.
What is a BFF?
When you consider an e-commerce shopping application, there are a number of microservices, and the communication between frontend and backend will be particularly chatty resulting in several network calls. A better solution would be a backend service that provides only the information required for my application. This is where the Backend-For-Frontend (BFF) pattern helps.
For example PayPal redesigned their checkout process to optimize their checkout times and eliminate unnecessary roundtrips.
Instead of the frontend application aggregating data by calling and processing information from multiple data sources and APIs, we create a BFF layer. This layer does the following:
- Receive request from the client application
- Call multiple backend services as required to get the required data
- Format the response with just the information required by the client
- Respond with the formatted data to the client application
This design approach helps:
- Simplify the frontend logic
- Avoid over-fetching or under-fetching
- Reduce the number of network calls that the client has to make, to render a page
Our Mars weather application redesigned with BFF would look like this. A single call from the client to the server retrieves all and only the information required.
Each client application can have its own BFF as shown below. This is really what BFFs are meant for.
Advantages of BFFs and a word of caution
- BFFs help mask the complexities of various backend services from the frontend application
- BFFs help with the separation of concerns – backend services can evolve on their own. BFF API forms a cushion to let frontend application evolve on their own and not worry too much about changes to backend services
While BFFs in general help simplify frontend applications, few things to keep in mind:
- Ensure you don’t start building business logic into it and convert it into an all-purpose API
- Don’t overuse BFFs by creating one for each client type
What is GraphQL?
Before we talk about how GraphQL fits into building a BFF, here is a quick view of what is GraphQL.
Unlike REST APIs, GraphQL allows the server to define the data it can provide as a DSL. The clients can send requests written in this server-provided DSL to get the data they need. This allows the clients to be in control of the response they receive, avoiding over-fetching or under-fetching.
While a detailed review of GraphQL will take a blog of its own, here is a short mind-map of GraphQL components before we discuss how GraphQL fits into building BFFs.
For our Mars weather app, the schema definition will look like this.
To query the data, the client will send a query DSL such as this to get both the weather data and the image of the rover.
To just get the weather data, the client can send a request thus:
By way of review of what GraphQL can do:
- Schema: The server defines the schema and query DSL – including data type for the data it is able to provide
- Query DSL: The client is able to send a query in the DSL supported by the server and receive an appropriate response
- Avoid over-fetching and under-fetching: The client is able to control the data it receives in response
- Documentation / Introspection: GraphQL endpoint provides a schema and query introspection that will enable clients to construct the query appropriately
You can find the code in this GitHub repository: mars-weather-service
How GraphQL helps build BFFs?
While BFFs as a design concept can be implemented using any appropriate technology, you should now be able to see how the features of the GraphQL map well to what the BFF pattern set out to do.
Pioneers who have successfully implemented BFFs using GraphQL
Many companies such as PayPal, Coursera and so on, were looking for an alternative to REST API to build custom solutions. Facebook was working on its own solutions – GraphQL which they open-sourced in September 2015. Since then GraphQL has seen an exponential rate of adoption among major companies. And the ecosystem is rapidly evolving. I expect with all the learnings, the technology is going to mature further over the next few years, making it easier not just for development but also for deployment at scale and operating in production.
Challenges to solve with GraphQL
While GraphQL is widely adopted and proven to be an excellent fit to implement BFFs, there are several missing capabilities and challenges compared to REST APIs that are far more mature.
- Limited native data types. In our Mars weather service example, we had the date as String. We can however create our own types
- Mature and simplified caching toolset available for REST compared to GraphQL
- Error handling and related tooling for GraphQL needs to mature further
- If improperly used, GraphQL APIs could result in performance issues
- Potential for Bikeshedding (time spent on largely tangential matters like network errors, content negotiation, and caching)
- Overall ecosystem and tooling options need to mature/expand further
Picking the right API paradigm: gRPC, REST, GraphQL
The key is to always use a solution that fits your requirement, instead of adopting a shiny new piece of technology.
- gRPC is ideal for communication between microservices within an enterprise
- REST APIs are ideal for publishing publicly available APIs
- GraphQL helps build BFFs
What is your experience with GraphQLs and building BFFs?
- Is GraphQL The Future? – Artsy Engineering
- Some thoughts on GraphQL vs. BFF (philcalcado.com)
- The Back-end for Front-end Pattern (BFF) (philcalcado.com)
- GraphQL vs REST: putting REST to rest (imaginarycloud.com)
- GraphQL: A success story for PayPal Checkout | by Mark Stuart | Technology at PayPal | Medium
- Introducing and Scaling a GraphQL BFF (infoq.com)
- The BFF Pattern (Backend for Frontend): An Introduction | by Viduni Wickramarachchi | Bits and Pieces (bitsrc.io)
- GraphQL Java (graphql-java.com)
- How Big Companies Are Using GraphQL in 2018 | StackShare
- Picking the right API Paradigm (phil.tech)