Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions docs/05-go-client/15-workflow-versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,72 @@ but you want to ensure new :workflow:workflows: are running on new logic, you ca
new `WorkflowType`, and change your start path (calls to `StartWorkflow()`) to start the new :workflow:
type.

## Safe Deployment of Versioned Workflows

When deploying workflow changes in production environments, you may want to separate the versioning
of the workflow code from the activation of new logic to ensure ability to roll back changes safely.
The `ExecuteWithVersion` and `ExecuteWithMinVersion` options provides this capability by allowing you
to control which version is returned when `GetVersion()` is executed for the first time.

### Step 1: Deploy with Compatibility

Initially, your workflow has the following code:

```go
err = workflow.ExecuteActivity(ctx, FooActivity).Get(ctx, nil)
```

To safely roll out changes that replace `FooActivity` with `BarActivity`, you need both versions
of your workflow code to be compatible with each other. Use `GetVersion` with the `ExecuteWithMinVersion` option:

```go
v := workflow.GetVersion(ctx, "fooToBarChange", workflow.DefaultVersion, 1, workflow.ExecuteWithMinVersion())
// equivalent to
// v := workflow.GetVersion(ctx, "fooToBarChange", workflow.DefaultVersion, 1, workflow.ExecuteWithVersion(workflow.DefaultVersion))
if v == workflow.DefaultVersion {
err = workflow.ExecuteActivity(ctx, FooActivity).Get(ctx, nil)
} else {
err = workflow.ExecuteActivity(ctx, BarActivity).Get(ctx, nil)
}
```

At this step:
- The previous version of the code supports only `DefaultVersion`
- The new version of the code supports both `DefaultVersion` and `1`
- The new version of the code is not yet activated, so workflows started on the new code will still execute the `FooActivity` (previous version)
- This makes it possible to safely roll back your changes if needed, as the previous code supports `DefaultVersion` only

### Step 2: Activate New Logic

When the previous version of the code is no longer running, you can activate the new code by removing the `ExecuteWithMinVersion` option:

```go
v := workflow.GetVersion(ctx, "fooToBarChange", workflow.DefaultVersion, 1)
if v == workflow.DefaultVersion {
err = workflow.ExecuteActivity(ctx, FooActivity).Get(ctx, nil)
} else {
err = workflow.ExecuteActivity(ctx, BarActivity).Get(ctx, nil)
}
```

At this step:
- Both versions of the code support both `DefaultVersion` and `1`
- The new version of the code is activated, so workflows started on the new code will execute the `BarActivity` (new version)
- This still allows safe rollback because both versions of the code support both `DefaultVersion` and `1`

### Step 3: Clean Up Old Code

When there are no running workflows using `DefaultVersion`, you can remove the corresponding branch:

```go
workflow.GetVersion(ctx, "fooToBarChange", 1, 1)
err = workflow.ExecuteActivity(ctx, BarActivity).Get(ctx, nil)
```

`ExecuteWithMinVersion` and `ExecuteWithVersion` options are particularly useful when you want to ensure that
your changes can be safely rolled back if needed, as both versions of the workflow code remain compatible with
each other throughout the deployment process.

## Sanity checking

The Cadence client SDK performs a sanity check to help prevent obvious incompatible changes.
Expand Down