When it comes to maintaining and deploying an API Gateway within an organization, you should always be aware of best practice. A gateway is an extra step between the client and the servers with the power to define a whole new interface, yet it’s so flexible and easy to implement that you might be tempted to start creating API interfaces without thinking about it - and end up creating problems for the future.
In this article we’ll outline some things you’ll need to keep in mind if you want to deploy an API Gateway in your ecosystem.
An API contract written in blood
As with any business relationship between two parties, creators and consumers of an API should also agree to an API contract. But this API contract is not a piece of paper, but the configuration file used to start the API gateway service itself. The API contract defines exactly how the API will respond.
Unless you are a solo developer consuming and creating your own API, once you publish a new endpoint in your API it’s quite hard to be 100% sure who will use it and how, especially in large organizations and public facing interfaces. Making changes to its definition or removing parts can have a big impact on your clients, break stuff and piss off developers. So treat your endpoints’ definitions as if they were written in blood and avoid making changes to existing endpoints.
Since it may only take you a minute to change the API contract and deploy it to production, you should avoid adding unnecessary features. Having a lot of endpoints is not a problem for the gateway, it’s a problem for you, the gatekeeper.
Make changes, but version all the things!
As a rule of thumb when you add endpoints, always use versioning. The greater the coupling between the client and the backend services, the greater the odds of breaking something in the next deploy of either of the components. If you need to change the definition of an endpoint, do it in another version and leave the previous endpoint as it is.
If you keep your API and endpoints properly versioned, your clients won’t get conflicts and wrong responses. It also helps with your release cycle, avoiding complex and expensive regression tests at the edge of your infrastructure.
Keeping that in mind, the interface exposed by the API Gateway will be your ultimate contract. Your backend services can all evolve, but as long as your gateway keeps its promise (its contract), all your existing clients will be happy.
Start by using a major version prefix in all your endpoints and keep that piece semantically meaningful. At the very least, you should consider creating endpoints with a prefix like
Versioning the code
Even more important is to track all changes in the API Gateway definition (the
krakend.json configuration file). Add the configuration file to git, or whatever your preferred source code management system is, so you can manage it properly and rollback when necessary.
Gateway and configuration in a single artifact
Since your contract should just depend on the configuration (where all the endpoints definitions are), it’s sound to demand that the configuration must be versioned and the critical parts (e.g: the service discovery) should not change dynamically. Let’s see the issues you create when you don’t do this.
It is impossible for the maintainers of every microservice to be aware of all of their clients’ needs. If every release impacts on their clients, everyone will become wary of new releases and the entire environment will start to rot.
On the other hand, if the microservice environment clients are too coupled to the services they are consuming data from, a known design problem appears: rigidity. When this happens, every release is also a pain due the “house of cards” effect.
A nice way to avoid problems like this is to coordinate the releases between the clients and the gateway maintainers so both parties can easily detect and avoid any changes in their contract.
In our experience, if the ownership of the contract (the gateway configuration) does not belong to the actual consumer or at least someone working closely with them, the contract tends to be forgotten about - until something breaks.
If owning the contract is as easy as keeping track of a JSON definition file containing the use cases, and know-how to proceed on exceptional situations, then it makes sense for the owner of the contract and the consumer to be the same person. This comes with implicit benefits in uptime and quality of the service (QoS).
State propagation and the CAP theorem
… it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:
- Consistency: Every read receives the most recent write or an error
- Availiability: Every request receives a (non-error) response – without guarantee that it contains the most recent write
- Partition tolerance: The system continues to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes
Since the configuration version used in the API Gateway could be considered a state, in clustered-based scenarios it shouldn’t be changed without requiring a coordinated effort. This effort is out of the scope of the service and it is easier to proceed with the API Gateway as with any other regular service in our environment.
There is plenty of writing from the past 20 years to support the statement that “stateless services are easier to scale”. When every node is the same as its neighbours, any one of them can be replaced without disruption and with no impact on the global performance of the cluster.
That’s because stateless services do not care about Consistency. And their reward is almost 100% uptime and complete resilency against partitions. These services do not require co-ordination, consensus or any other type of internal signaling for reaching an agreement before committing to a change in the state… because they can’t change their state at all!
In the API Gateway layer, the most important metrics are related to the responsiveness and the throughput of the service. Enforcing some level of co-ordination between the members of the cluster will impact on these metrics and in your QoS. It’s easier and more effective to manage the configuration with a more complex rationale than a template dumping a list of your registered services in, let’s say, your kubernetes cluster.
Releasing a new version
Now with an agreement on the API contract let’s put our gateway into production. We recommend you add a step to create and push a Docker image that will be deployed later to your continuous integration pipeline.
Creating your KrakenD docker image
If you don’t use Docker in production you can create a simple artifact with 2 files inside: the binary and the configuration file.
Dockerfile will look like the following:
COPY krakend.json /etc/krakend/krakend.json
Now your pipeline only needs to:
- Build the image, e.g:
docker build -t $IMAGE .
- Tag the image (as latest and the specific commit
- And push it to the registry:
At this point you have a new Docker image available in the registry every time you push changes to the desired branch.
The blue/green deployment strategy
Almost all our Enterprise customers live in the cloud, where it is very easy to spin up new machines and destroy them later (or maybe not machines but just containers). No feelings attached!
A very simple way of deploying KrakenD is using the blue-green deployment strategy. If you are in AWS you can use their service directly.
If you are unfamiliar with the blue/green technique all you need to know is that you start a new set of services with the desired configuration, check if they work properly, and then you move all the traffic to them. Previous services can be shut down when there is no traffic left, or kept for a while for quicker rollbacks.
For a further explanation read Martin Fowler’s article
In this article we shared our experience deploying API Gateways with some recommendations that might be handy for you. We’ve stressed the importance of respecting the API contract and thinking thoroughly before adding more endpoints to the system. Introducing another moving piece like an API Gateway comes with organizational challenges that you’ll need to work on. As a first step to avoid future problems, introduce versioning in your endpoint definition from the first created service, even your backends do not have versioning.
Finally, we have seen an example on how easy is to deploy the API gateway. We used Docker for the sample but being a binary and a configuration file there are numerous ways you could do this.
You made it this far?
Thanks for reading! If you like our product, don’t forget to star our project!
Categories: Technical Insights & Best practices