Killing BFFs with GraphQL

At HomeAway, we’ve been replatforming our web applications using Node.js and React. Developers adopting this new stack often ask if these applications should be handling “API calls” made from the browser.

The short answer is “yes, always,” but let’s talk a little about why.

Building client-side specific services or BFFs.

Welcome to Backends-for-Frontends

In the diagram above, you can see what was somewhat typical of prior thinking on this subject. A “thin” application serves a page which then subsequently interacts with services through a backend-for-frontend (BFF) API.

Sometimes the API call is proxied through the thin server side app, sometimes not. The purpose of these BFFs are to share orchestration, business logic, and to provide models that are more UI friendly than are typically served by the back-end services. For example, a BFF might serve a composition of data from one or more services, and a mobile client may need some subset of that.

Some of the challenges with BFFs:

  • Difficult to manage cross organizationally.
  • Can have unpredictable capacity requirements.
  • Adds additional architectural complexity (moving parts).
  • Pushes front end concerns away from the application.
  • Can be a single point of failure.
  • Difficult to predict downstream changes.
  • Not as friendly for isomorphic apps.
  • And on… and on…
BFFs may lack visibility into how breaking changes affect different apps.

Another approach is for a client to interact directly with the application that served or rendered it. This provides some immediate benefits:

  • Less deployment complexity.
  • Less interdependence between software and teams.
  • Insulates user experiences from change.
  • Exposes less API surface area.
  • Isomorphic friendly.
Client side interacting directly with application that served them.

Although collapsing the orchestration into the application improves the picture, there are still issues in common with BFFs. The application must still contain logic to differentiate between the data needs of different client types (native, web, mobile web, etc), and the contract between the client side and server side is fixed.

Here comes GraphQL

To make these interactions even cleaner and better serve different clients, we’ve begun moving to GraphQL for fetching data. GraphQL was developed by Facebook in part to help them deal with the mounting complexity of managing components in an evolving API graph. At HomeAway, we face similar challenges as we break down monoliths and migrate to microservices.

GraphQL allows UIs to declaratively interact with data and insulates them from how that data is ultimately resolved on the server. We don’t need to worry about building UI friendly models anymore because the UI specifies what it is interested in. In addition, GraphQL can be optimized more readily than typical AJAX requests, resulting in fewer over the wire calls.

Client side interaction over GraphQL.

We’ve worked to make GraphQL more reusable by breaking up schemas into “partials” — components consisting of types and resolvers — packaged into separate NPM modules. Developers can pick and choose different modules to use with their app and the partials will dynamically be merged into a single executable schema.

Example theoretical partial:

const types = `
type Property {
.
.
.
}
extend type Query {
property(propertyId: Int!) : Property
}
`;
const resolvers = {
Query: {
property(_, { propertyId }, context) {
.
.
.
}
}
};

Partials are specified in the application’s configuration and merged into an Apollo GraphQL server. This makes it easy to not only add data orchestration to applications quickly, but to spin up standalone GraphQL servers if necessary. Native mobile application teams can take advantage of this to develop independently of web teams while still utilizing the same shared code for data. In some ways one might think of this as BFFs v2, only without many of the shortcomings that previously existed.

GraphQL partials may be re-used.

In rethinking our data interactions we’re learning that code is easier to share and maintain than services, and this decoupling is an accelerator for teams. At HomeAway, we’re seeing the results of this work with native mobile and web teams developing and sharing their GraphQL partials and previously monolithic APIs for mobile are replaced. We’re excited to see how this continues to impact the development of applications, and have begun to experiment with the same pattern for some of our public APIs.

2018 is going to be the year where GraphQL goes mainstream. With the unveiling of platforms like Amazon’s AppSync and frameworks like Graphcool in the tail end of 2017, mass adoption is just around the corner.


Read more about HomeAway on Medium.

Like what you read? Give Trevor Livingston a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.