Workflow versioning

Version your workflow to evolve your service

Posted by Automatiko team on July 01, 2022 · 8 mins read

Workflow versioning

In Automatiko workflows are the base artifact that the service, function or function flow is built from. And by that they are considered the entry point from the consumer point of view. Workflows as any other software component will evolve over time, somtimes gracefully without major (or breaking) changes and sometimes there will be a need for more drastic change in business logic.

Versioning on the other side is one of the most popular approaches to evolve your services in controlled and safe way. When it comes to workflows, it's no different. Workflows, on all levels - meaning regardless if they are top level workflow or a subworkflow - can be versioned.

First and foremost is to identify when to change the version of your workflows. By introducing version of the workflow in Automatiko this will directly translate to the service api (both ReST and GraphQL). So by that the consumers of the service will be affected in a way that they need to switch to the new version as soon as they will be able to.

Versioned REST api Versioned REST api.

So when to change the version?

Best answer to that is when the change introduced is not backward compatible. Meaning currently running workflow instances cannot continue on it. To give an example a non backward compatible change is remove of an activity of the workflow that is a wait state activity. Wait state activity is an activity that workflow instance can pause on. As this means such activity will be stored as part of the instance state. When it is removed and the version is not changed, all instances that are in that activity will no longer work and by that will be in sort of a dead end state.

The same applies to data model, if the change introduces new fields of the data model then it is considered to be compatible unless new fields are required and they do not have any default value.

So as long as the changes are compatible keep the version unchanged.

How versioning works in Automatiko

Workflows that are versioned will expose that version number via service api. Depending on which service interface is used it will be as following

  • REST - service operation path will be prefixed with version number /v1/parts where 1 is the version number
  • GraphQL - queries, mutations and subscriptions names will be suffixed with version number create_parts_1
So as you can see there is no need to do extra work to make the service apis to be versioned as well.

Set version of the workflow via properties Set version of the workflow via properties.

Worth mentioning is also the fact that workflows that are versioned needs to take into account messaging aspect. Espeically important is the consumer of messages. This is usually represented as

  • message start event
  • intermediate message event
  • boundary message event
The reason why it is important to take this into account is that if different versions of the workflow will listen on the same queue or topic they might "steel" messages from each other. There can be different approaches to this problem
  • for start events it might be as simple as removing the message event to allow to only start new instances from latest version
  • for any type of message event easiest is to use dedicated queues/topics to separate consumers

Last but not least when using workflow as function of workflow as function flow versioning is also taken into account. For instance with workflow as a function flow that relies on cloud events the cloud event's type attribute includes the version suffix org.acme.travels.greetings.v2_2 that corresponds to workflow version 2.2

Versioning best practice

The most important best practice is to change version only when introducing non backward compatible change. Other best practices are:

  • When creating new version start from a copy of the current version and expand from there
  • Use number based versioning as it will allow to calculate latest version
  • Run multiple versions at the same time as long as there are active instances of the older versions then remove unused versions
  • Use export / import features of process management addon to migrate between versions
These are just few bullet points that could become quite handy when versioning your workflows and by that your service apis. Other will emerge once you start putting this into real life use cases.

Routing between versions

Introducing versions of the workflow, introduces versions of your api. In most of the cases this will not cause any issues but will require migration for consumers of the service to latest version. To ease with that, maintainers of the service can turn on feature called route to latest version. The main purpose of this feature is to allow requests to use unversioned paths e.g. /parts instead of versioned one like /v2/parts.

This mechanism is smart enough to find out if the request can be safely routed to latest or not. The main decision point for it is the existence of instance identifier. If operation contains instance id then it is routed to the version that instance belongs to, but if the operation does not have instance id then it goes to the latest version. Following are examples of both operations:

  • GET - /parts/12345 - will go to version that hosts part with id 12345
  • POST - /parts - will start new part instance on latest

To enable that add quarkus.automatiko.service-route-to-latest=true inside the application.properties

NOTE: This routing is supported only for REST service interface

Instance migration between versions

As soon as we introduce multiple versions of the workflow a common question is how to migrate between versions. This is quite complex topic as the most important parts are

  • how to map not compatible activities?
  • how to migrate data model?
There is no simple answer to that, but luckily Automatiko comes with an export/import feature that comes with process management addon. With this we can export complete workflow instance (including all their dependencies like sub instances, files, timers etc.) and then import it into another versions of the workflow. Since the exported instance is represented as JSON it can be used to manipulate it to fit into the new version requirements.

Although export/import provides a way to migrate instances between versions it is not a complete and automatic mechanism to move high volumes of instances. There will be a need to do some alterations between export and import.

Complete scanario of using versioned workflows

At the end, have a look at less than 10 min video showing how versioning works in Automatiko and how simple it is to evolve your service based on workflows.

Photographs by Unsplash.