Backend For Frontends, Optimized Server Adapters, and GraphQL
Building APIs at scale, especially as the number of use cases and different clients grows large, poses a number of problems. This is especially true when your domain grows large, and different clients need to get data from a lot different bounded-contexts, in different ways.
Over the years, great companies have found their own way of dealing with this problem. I recently thought about this evolution and I thought it was interesting, so here we go.
Client Optimized Server Adapters ☁️
6 years ago, at Netflix, this problem was solved in a very particular and cool way. The team at Netflix was getting to the limits of the OSFA (“One Size Fits All”) approach with their REST API, especially since they were approaching more than 800 different client types. That’s a lot of clients, especially for an internal API, but imagine managing a large public API.
The approach they took was to introduce a middle layer between the typical Client & Server interactions. In essence, they are pushing some code that used to be considered client code to client optimized API servers, which in the end, simplifies client logic a lot by avoiding under/over fetching, error handling, formatting, etc.
This approach lets Netflix optimize requests and responses from the client, but also reduce the number of API calls from the client (let the middle tier server do it instead), but also lets client teams work in a distributed way. Reminds you of something yet?
BFF 👭
Around the same years, a team at Soundcloud was also facing similar problems, their solution? The Backend For Frontends Pattern.
The implementation at Soundcloud is quite different from the Netflix one, but don’t you find the concepts are pretty similar? The backends for frontends here act as those Netflix middle tier optimized servers, providing optimized endpoints per client.
The idea was that having the team working on the client own the API would allow for them to move much quicker as it required no coordination between parts
There’s also a similar cultural / workflow aspect here, they wanted teams to evolve their APIs as distributed as possible, without needing to evolve a One Size Fits All API. Very interesting.
What about our Facebook friends? 💻
So… with all this, I wondered what Facebook was working on during these years, it seems a lot of us were facing similar problems 🤔
That’s right, in 2012, Facebook was also thinking of ways of solving similar issues, and solutions.
We were frustrated with the differences between the data we wanted to use in our apps and the server queries they required.
GraphQL also allows us to work in a more distributed way, although maybe not as obvious as the BFF approach. In fact, if we take a look at the GraphQL introduction post again:
When you’re adding new product features, additional fields can be added to the server, leaving existing clients unaffected.
So what am I trying to say here? To me, GraphQL is another solution part of the set of possible solutions to the problem of OSFA APIs. It is quite different from the other ones I talked about here, but aims to solve similar problems.
In fact, these days, it almost seems to me that a GraphQL API really ends up acting as a client optimized API, but generic enough to handle any client. It is kind of a monolithic approach to Backend-For-Frontends, using a type system and powerful query language for clients to use what they need.
Careful though, if we want this to be true, especially with a large number of clients or a public API, we must design the schema having that in mind, and not build a OSFA GraphQL API.
This leads me to a schema design approach we have recently been using more and more at GitHub that has simplified thinking about design and solved some problems we had:
- Don’t be afraid to provide many ways to do similar things
And specifically:
- Prefer many optimized fields/mutations to one very smart/generic field or mutation.
That’s it! Hope this will be helpful to some of you in terms of where GraphQL is coming from (at least from my point of view) and how we can use that to lead us to better schema design and a more distributed way of working on a GraphQL Schema.
Share your thoughts on this with me here or on Twitter 🐦! Thanks for reading 💚