API Gateways are emerging as an essential component in a microservices architecture. At one end of the spectrum, at its simplest an API Gateway can be thought of as a proxy that presents a single point of entry for all the external clients that talk to microservices. As such, a major feature provided by an API gateway is that it simplifies and shields the clients from the inherent complexities of a microservices world. At the other end, at its most complex, it can address numerous cross cutting concerns that are considered common to all microservices. It can assist the individual microservices by letting them stay true to the Single Responsibility Principle (SRP) and provide a convenient means to address common concerns that are not related to the core functionality of the service but are none the less essential supplementary services required for the proper functioning of the system as a whole.
API Gateway as an Orchestrator
Microservices by their very nature are designed to be finely granular and as per the SRP do only one thing and do it well. Contrast that with how clients usually operate. A single web page or a single screen on a mobile device will include an aggregated view based on information from several related areas. So a client, for presenting any non-trivial functionality, will need to interact with several microservices and aggregate all their responses and form a cohesive representation of it in one go. This implies that clients are better suited for a coarser level of interaction. As the granularity of the services increase, so too does the number of moving parts involved in servicing a single client side request. In addition, the dynamic nature of the services, as in common in a distributed system with virtualization/containerization, adds to the complexity of locating the individual services one has to interact with.
The other obvious (or may be not so obvious) issue, aside from the complexity of the interactions, is that of the chattiness introduced by having the client interact at the level of individual services. This can become a major issue, especially so if your clients are mobile devices. Given the restrictions of the mobile environment (unreliable networks, limited data plans, bandwidth issues, battery life etc) it is simply not practical to have such chatty communication over the network. For efficiency and performance, both at the client and server side, it becomes imperative to optimize on the number of network calls between the client and the services.
So in light of these concerns, an important design question that arises is that of the choice between letting the clients handle the interactions individually and deal with the associated complexities OR that we shift the complexity to the server side and thus let the clients deal with a simpler coarser interface ?
For all but the most trivial of applications, the answer is going to be the latter. The entity that actualizes the answer is the API Gateway. The API gateway acts as an orchestrator and fans out or splits down the single request (in parallel, sequential etc) from the client into multiple requests to microservices, handles the responses, aggregates and sends a single response upstream to the client. Care is needed here to ensure that business logic does not seep in to the gateway but that we confine it to only handle the orchestration aspect of it.
Another area in which an API gateway can add value is in helping support changes and evolvability of the API to a certain extent, since it provides a layer of abstraction between the APIs the services provide and the APIs the clients consume. This decoupling gives more autonomy on the server side to change the granular APIs and not require the clients to change or even become aware of them. Of course, this only applies to non-breaking changes but it is still good to have this autonomy and keep the scope of the ripple effects of API changes within the server side.
Given its place as the layer between the clients and services, an API gateway is also a good place to handle various transformations and translations of data and protocols, if there is a mismatch between what the client sends and what the services expect. This is especially useful in a microservices architecture where numerous technology stacks are in play and thus compatibility issues abound.
There are two variations in terms of how to go about designing the API interface part of gateway. One is to have a single general purpose API that all clients use. The other interesting pattern called the Backends for Frontends (BFFs) is to have an API per client type or as explained in this post and this post – An API per user experience. Netflix has taken an approach where they have a general API fronting adapters for each kind of client that they support. All three articles are good reads if you want to explore in detail.
API Gateways for Cross Cutting Concerns
There are several functionalities that are common to several microservices such as security, authentication, authorization, service discovery/routing, monitoring, logging to name a few. Expecting each microservice to implement these functions individually is definitely not a good idea, both in principle and in practice. A desirable and more importantly, familiar approach is to have a single place to provide these functions outside of the services themselves and prioritize the services to focus exclusively on the business logic. Since the API gateway is a single entity through which all external requests are routed, it naturally seems to fit into this role. Many API gateways available today follow this pattern. Kong is an opensource API Gateway built on top of Nginx, that provides several of these functions. Netflix, Zuul, Spring Cloud gateway and Amazon API Gateway also provide similar functionality. This space is nascent and still growing. It will be interesting times ahead indeed.
Somethings to watch out for is to ensure that an API gateway does not creep into the business logic space which could eventually result in a tightly coupled, bloated monolith. This will significantly reduce the benefits of having microservices behind this bloated monolith gateway. The API gateway is an essential component, right front and center in the critical path for all requests in the system. As such all the design solutions commonly used in highly available distributed systems in mitigating Single points of failure should be applied to the API gateway as well.
This post has only touched upon the API gateway at a high level of abstraction, a forest rather than the trees level of look. I have to mention the Service Mesh, another interesting concept that builds upon some of these issues and takes it further. Built as a network of side cars, the service mesh complements microservices, in much the same way as the API gateway does, in managing common concerns. A strong point in their favor is that they also play well with containers. Service meshes could replace an API gateway for dealing with the cross cutting concerns. This is again a very nascent area and one to watch for exciting developments.
Note that this article is part of the Microservices series. You can read the previous ones here : Prelude, Introduction, Evolution, Guiding Principles, Ubiquitous Language, Bounded Contexts, Communication Part 1, Communication Part2, Communication Part 3, Communication Part 4, Communication Part 5, Kafka, Time Sense, Containers
Microservices and API Gateways by Nginx