How to version an API to easily deploy many versions?

Last Updated on 30/05/2021 by Patryk Bandurski

We version the APIs to track the changes we made to them. Most of the time, it is sufficient to host just a single, major version of the API. However, there are cases when we need to host the previous version for backward compatibility reasons. In this article, I decided to share my thoughts on API versioning in the MuleSoft CloudHub environment. In the end, you should understand how to build an API to enable multi-version deployment.

Where to place API version in the URI?

It is recommended to use semantic versioning to track the changes we are introducing. We can distinguish major, minor, and patch parts like MAJOR.MINOR.PATCH. As only the major version introduces backward-incompatible changes, it is recommended to have just the MAJOR part in the URI. MuleSoft recommends v{major} pattern for instance v1, v2 etc.

Semantic versioning

Now, that we know that in the URI should be the major version of the API, where to put it?

API version in the base path

Down below, you can see two viable solutions. On the left-hand side, we have a case with two versions of API that are deployed separately. That means that in Runtime Manager, you will see two applications, one dedicated to the v1 version and the second one for the v2 version. Of course, the application name must be unique, so we need to add some random text. Like on the diagram, emphasized with the red font. On the right-hand side, we have an approach when we blend versions into a single application. It means that our MuleSoft application contains both v1 and v2 endpoints. In Runtime Manager, you will find just a single occurrence of the API.

Two seperate deployment API one for version v1 and one for version v2
Single API having v1 and v2 application’s logic

From the two presented approaches, I prefer the first one. Although we need to use more vCores, we can manage the application independently. What is more, we can, as time progress, decrease the resources and importance of the deprecated/older version.

MuleSoft application listener configuration

On the screenshot below, you can see generic settings of HTTP Listener. The base path is set to /api/${api.version}/*. api.version is the property name having a major API version, for instance, v1. When the application starts, it will listen on /api/v1/* base path.

HTTP Listerer general configuration with path specified as /api/${api.version}/*
HTTP Listerer general configuration with path specified as /api/${api.version}/*

API version in the application name

The second strategy is to put the API version is the application name. It means that we will have as many applications deployed as many versions we would like to host independently. Down below, we have two versions of an API. In the Runtime Manager, you will notice two applications. As you remember, in the CloudHub application name is part of the hostname. As a consequence, we will have URIs like in the example below.

API version included in the application name (hostname)

The advantage of that approach is flexibility in developing a newer version without affecting the old one. We can manage the APIs independently and put better security and quality of service policies to the APIs based on their version. It has another advantage; we can see the progress of moving the consumers from the older version to the newer one. The obvious disadvantage is the increased resource usage as we require an additional deployed application.

This pattern can be combined with the first approach from the previous section. Instead of random characters we can put the API version.

MuleSoft application listener configuration

On the screenshot below you can see generic settings of HTTP Listener. The base path is set to /api/* without specifying the version number, as it is done in the application name.

HTTP Listerer general configuration with path specified as /api/* without version number
HTTP Listerer general configuration with path specified as /api/* without version number

API Management of multiple versions

Once you prepared the API specification and published it on Anypoint Exchange, you add API to manage in API Manager. From the details view, you take Autodiscovery ID to put into the application. Otherwise, the API implementation won’t connect to the API Manager. When you publish a new major version to Anypoint Exchange, for example, v2, you need to add API to manage in API Manager, as you did it previously. As a result, we have a view similar to the one below:

Two managed versions of an API - here v1 and v2 and both are active
Two managed versions of an API – here v1 and v2 and both are active

Just remember that both version won’t share the same Autodiscovery ID and you need to provide them appropriately.

CloudHub deployment configuration

Down below, you can see an extract from the pom.xml file with the plugin definition responsible for the deployment of the application onto CloudHub. In the properties element, I defined the current major version of the API (line 2). It can be later resolved using the following syntax ${api.version}. Apart from that, I defined the application name (line 4) and prefix (line 3). In the highlighted line 19, you can see the applicationName property that is built from three properties.

<properties>
	<api.version>v2</api.version>
	<cloudhub.application.prefix>myproject</cloudhub.application.prefix>
	<cloudhub.application.name>portal-eapi</cloudhub.application.name>
    ....
</properties>

<plugin>
	<groupId>org.mule.tools.maven</groupId>
	<artifactId>mule-maven-plugin</artifactId>
	<version>3.4.2</version>
	<extensions>true</extensions>
	<configuration>
		<cloudHubDeployment>
			<uri>https://anypoint.mulesoft.com</uri>
			<muleVersion>${app.runtime}</muleVersion>
			<username>${username}</username>
			<password>${password}</password>
			<applicationName>${cloudhub.application.prefix}-${cloudhub.application.name}-${api.version}</applicationName>
			<environment>DEV</environment>
			<region>us-east-1</region>
			<workers>1</workers>
			<workerType>MICRO</workerType>
			<properties>
				<anypoint.platform.client_id>${ap.client_id}</anypoint.platform.client_id>
				<anypoint.platform.client_secret>${ap.client_secret}</anypoint.platform.client_secret>
			</properties>
		</cloudHubDeployment>
	</configuration>
</plugin>
...

When we now invoke mvn clean package deploy -DmuleDeploy myproject-portal-eapi-v2 application will be created/redeploy. We can imagine that a couple of weeks ago api.version was equal to v1 and myproject-portal-eapi-v1 application is deployed on the CloudHub

Sample application can be found here on my GitHub account.

More about deployment maven plugin you can find in the MuleSoft documentation.

Summary

When you need different versions of your API deployed independently, you have a couple of ways to implement it. You can either embed the API version in the application name or in the base path of your HTTP Listener. I recommend for the CloudHub deployment the first approach as is the simplest one. It is just a matter of a well-defined deployment script that specifies the application name with the version number.

How to version an API to easily deploy many versions?

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top