This tutorial is focused on how _Backend For Frontend (BFF) design pattern_represent Mobile App developer “Best Friend Forever” and in particular how different technology could help implementing the best BFF that will result on best reactiveness and responsiveness for Mobile Apps.
Generally speaking BFF goal is to simplify client app development time decoupling “service API” calls, potentially reducing the number of calls and sharing eventually some logic across different client implementations optimizing in general Networking and Data transformation while adding shared capability for data Joining, Paging, Caching, Syncing, Streaming etc. and finally enforcing security and other policies.
There are already lots of tutorials on Internet that introduce this now pretty common design pattern. Here, without talking about multi-channel, microservices, api gateway, service mesh and without using any other modern “server” terminology, we simply say that a BFF is the “middleware” between the mobile app and every “service API” the mobile app need to call on Cloud or on premise.
This tutorial focus more specifically on how the BFF pattern could help on simplify access to these service API interfaces and how in particular the adoption of the gRPC protocol can help, a lot indeed, on reducing data size, optimizing network and implementing and enforcing bunch of shared infrastructure functionalities.
Of course as in many other fields there is no silver bullet here. Other interfaces such as GraphQL could provide other benefits on some scenarios and specific mobile technologies such as URLSession background download tasks on iOS could provide very powerful control on network optimization on specific mobile contexts (i.e. limited multitasking)
In this tutorial we will create a Mobile App and a BFF server to practically demostrate the advantages of this design pattern.
We will create a Pokédex mobile app that using the publicly available http://pokeapi.co/ REST API will allow the user to search Pokemons by name or by type and it will display for each Pokemon found the following information:
In order to get all this data the following backend REST APIs will be used:
But wait a minute? These Pokemon APIs are just simple REST APIs that I could easily directly call from the mobile App itself. Why I need gRPC and even more important why use a BFF ?
That’s right. These API could be used directly by the Mobile App itself but let’s see in the picture below what could be the disadvantages of these simple approach.
First of all we can see that even this super simple App needs to coordinate data coming from three different network API calls.
Basically for searching all pokemons of a particular type we need to first call the /type Rest API to have a list of Pokemon name or Id and then for any singular Pokemon in this list we need to call the /pokemon Rest API to have basic information like name, types, heighs and width and also call the /pokemon-species Rest API to get the habitat information.
Other than the need to “orchestrate” calls to different Rest APIs another very important thing to focus on is that all these pokemon Rest APIs return much more data that we actually really need for rendering our app user interface.
Indeed in this sample iOS Mobile App we will use a very classic UICollectionView interface and we will need to show in the collection cells only the Pokemon information we introduced above (name, image, types etc.). These pokemon Rest APIs will instead transmit over the network (potentially on cellular network) lot of other data that we really don’t need at all in our simple App.
Is it more clear now the role for a BFF server in terms of simplifying the orchestration of different backend API calls but also providing the benefit of filtering and transmitting on the network to the Mobile App only the data that are strictly needed by the App.
There are lot of different technologies available today for implementing this BFF server. Native iOS mobile app developer can now use even Swift on Linux and server frameworks such as Kitura or Vapor to easily implement these BFF. Adoption of Apple open source Swift Nio library in the coming new release of these Swift Server framework will provide soon also lot of more efficiency and scalability (see https://medium.com/@JMangia/apple-swiftnio-netty-vert-x-grpc-and-service-mesh-ab5840c1b71c).
Node.js is also one of the most used platform for implementing this kind of BFF server as it provides extreme simplicity as well as lot of benefits from the adoption of the event loop architecture and its single thread async I/O support.
With Node.js and Javascript framework such as Express.js is super easy to implement this kind of BFF server. In the Github repository associated with this tutorial you’ll find a Node.js simple implementation of this REST BFF server under the BFF/Rest folder.
As we discussed before in the introduction of this tutorial the BFF is also the place where implement infrastructure functionalities such as authentication, authorization, caching and other generic functionalities. In our BFF Node.js implementation in particual a local in-memory cache is implemented using the Javascript Node-Cache package in order to locally store the data returned from the backend PokeApi and reduce the network traffic towards the backend.
We already said that BFF could also provide a simplified API interface to the Mobile App. In our specific case our BFF expose a unique and generic /Search API that it is used by the mobile App for searching both a single specific pokemon name or for searching all pokemon from a particular type name.
The diagram below illustrates the pseudo code implementation of this single client API and in particular how it basically orchestrate calls to the different PokeApi calls we have already introduced above.
With such a generic /Search API the UI of our Mobile App could be simplified a lot providing basically a single user experience for searching both per pokemon type or per pokemon name at the same time, without necessarily asking the user to tap on any other button on the screen but instead having the mobile app itself, with the help of the BFF, butter understand the simple generic intent of the user to just search for a name.
Anyway this new abstraction layer introduced by the BFF with this optimized and simplified /Search API produce the following very critical issue on the final user experience: the mobile App need now to wait the execution and the network transmission of the output from the BFF /Search API before getting all the data needed to reload and render the UICollecionView.
Basically before start displaying the new data to the user the Mobile App need to wait that the BFF collects, from the cache or from calling the PokeApi backend Rest API, all the data needed for satisfying the search request.
Here is finally the part where we are going to see the benefit that the adoption of the gRPC protocol could provide in terms of responsiveness and reactiveness to our Mobile App.
It is not a goal of this tutorial to provide a full introduction of the gRPC network protocol and of the Protocol Buffer data protocol. Lot of great tutorial already exist on the Internet.
We will simply concentrate here on the advantages that the “transparent” adoption of modern HTTP/2 network protocol could provide to our BFF implementation and to the communication between the Mobile App and the BFF just simply using a gRPC service interface that will support optimized HTTP/2 streaming networking.
The diagram below anticipate basically this new capability of the BFF pattern using gRPC protocol to directly stream to the client Collection View the data collected from cache or from Rest API call to the PokeApi backend and immediately and continuosly provide feedback to the user just in time without waiting for the full time to execute the entire search operation.
This is basically the ProtoBuf/GRPC interface defined for our BFF Search service.
As you can see the searchPokemon gRPC API (on line 24) is defined as a Server-to-Client streaming gRPC interface that will stream objects of type Pokemon described in the same protobuf file (lines 5–15).
Once we have our protobuf file describing the proto data structure and the gRPC service interface of our BFF API we can generate the corresponding Swift file to incorporate, together with the entire Swift gRPC package stack, in our iOS Swift Mobile App project.
Once installed the gRPC runtime and the Swift ProtoBuf and the GRPC plugins (follow instruction from Swift GRPC github site) you can easily execute the following command line to generate these Swift output file to include in the XCode project:
protoc <your proto files> \--swift_out=. \--swiftgrpc_out=.
The following Swift PokemonDataSource class simply wrap access to the protoc/grpc autogenerated swift file in order to simplify access to the gRPC interface from the view controller implementing the UICollectionView.
The Swift view controller class in this way will simply call the datasource.searchNewPokemon gRPC wrapper method and the passed completition block from the view controller will be called back for any pokemon data streamed from the BFF server over the gRPC — HTTP/2 network interface.
The Swift gRPC stack currently support also the server side code generation but for completeness of this sample tutorial I chosed to use again Node and Javascript to code the following gRPC BFF implementation:
Full source code for this tutorial for both Client and BFF projects is provided at this GitHub repo:
JacopoMangiavacchi/PokemonBot_PokemonBot — Swift GRPC Streaming BFF test_github.com