Roll out and pin Workflows
This page covers Rolling out changes with the CLI, Marking a Workflow Type as Pinned, Moving a pinned Workflow, and Migrating a Workflow from Pinned to Auto-Upgrade.
Rolling out changes with the CLI
Next, deploy your Worker with the additional configuration parameters. Before making any Workflow revisions, you can use
the temporal CLI to check which of your Worker versions are currently polling:
You can view the Versions that are part of a Deployment with temporal worker deployment describe:
temporal worker deployment describe --name="$MY_DEPLOYMENT"
To activate a Deployment Version, use temporal worker deployment set-current-version, specifying the deployment name
and a Build ID:
temporal worker deployment set-current-version \
--deployment-name "YourDeploymentName" \
--build-id "YourBuildID"
To ramp a Deployment Version up to some percentage of your overall Worker fleet, use set-ramping version, with the
same parameters and a ramping percentage:
temporal worker deployment set-ramping-version \
--deployment-name "YourDeploymentName" \
--build-id "YourBuildID" \
--percentage=5
You can verify that Workflows are cutting over to that version with describe -w YourWorkflowID:
temporal workflow describe -w YourWorkflowID
That returns the new Version that the workflow is running on:
Versioning Info:
Behavior AutoUpgrade
Version llm_srv.2.0
OverrideBehavior Unspecified
Marking a Workflow Type as Pinned
You can mark a Workflow Type as pinned when you register it by adding an additional Pinned parameter. This will cause it to remain on its original deployed version:
// w is the Worker configured as in the previous example
w.RegisterWorkflowWithOptions(HelloWorld, workflow.RegisterOptions{
// or workflow.VersioningBehaviorAutoUpgrade
VersioningBehavior: workflow.VersioningBehaviorPinned,
})
@WorkflowInterface
public interface HelloWorld {
@WorkflowMethod
String hello();
}
public static class HelloWorldImpl implements HelloWorld {
@Override
@WorkflowVersioningBehavior(VersioningBehavior.PINNED)
public String hello() {
return "Hello, World!";
}
}
[Workflow(VersioningBehavior = VersioningBehavior.Pinned)]
public class HelloWorld
{
[WorkflowRun]
public async Task<string> RunAsync()
{
return "hello world!";
}
}
@workflow.defn(versioning_behavior=VersioningBehavior.PINNED)
class HelloWorld:
@workflow.run
async def run(self):
return "hello world!"
class HelloWorld < Temporalio::Workflow::Definition
workflow_versioning_behavior Temporalio::VersioningBehavior::PINNED
def execute
'hello world!'
end
end
setWorkflowOptions({ versioningBehavior: 'PINNED' }, helloWorld);
export async function helloWorld(): Promise<string> {
return 'hello world!';
}
Moving a pinned Workflow
Sometimes you'll need to manually move a set of pinned Workflows off of a version that has a bug to a version with the fix.
If you need to move a pinned Workflow to a new version, use temporal workflow update-options:
temporal workflow update-options \
--workflow-id "$WORKFLOW_ID" \
--versioning-override-behavior pinned \
--versioning-override-deployment-name "$TARGET_DEPLOYMENT" \
--versioning-override-build-id "$TARGET_BUILD_ID"
You can move several Workflows at once matching a --query parameter:
temporal workflow update-options \
--query="TemporalWorkerDeploymentVersion=$TARGET_DEPLOYMENT:$BAD_BUILD_ID" \
--versioning-override-behavior pinned \
--versioning-override-deployment-name "$TARGET_DEPLOYMENT" \
--versioning-override-build-id "$FIXED_BUILD_ID"
In this scenario, you may also need to use the other Versioning APIs to patch your Workflow in the "fixed" build, so that your target Worker can handle the moved Workflows correctly. If you made a version-incompatible change to your Workflow, and you want to roll back to an earlier version, it's not possible to patch it. Considering using Workflow Reset along with your move.
"Reset-with-Move" allows you to atomically Reset your Workflow and set a Versioning Override on the newly reset Workflow, so when it resumes execution, all new Workflow Tasks will be executed on your new Worker.
temporal workflow reset with-workflow-update-options \
--workflow-id "$WORKFLOW_ID" \
--event-id "$EVENT_ID" \
--reason "$REASON" \
--versioning-override-behavior pinned \
--versioning-override-deployment-name "$TARGET_DEPLOYMENT" \
--versioning-override-build-id "$TARGET_BUILD_ID"
For a complete runbook covering batch recovery, drainage handling, and how to choose between Versioning Override and Reset-with-Move based on each Workflow's state, see Recover pinned Workflows after a bad rollout.
Migrating a Workflow from Pinned to Auto-Upgrade
There may be times when you need to migrate your Workflow from Pinned to Auto-Upgrade because you configured your Workflow Type with the wrong behavior or you've pinned a really long-running Workflow by mistake.
Pinned Workflows can block version drainage, especially when they run for a long time. You could move the Workflow to a new build, but that would just push the problem to the next build.
In order to make this change, you need to change the versioning behavior for your Workflow from Pinned to Auto-Upgrade.
You can use temporal workflow update-options for this:
temporal workflow update-options \
--workflow-id "$WORKFLOW_ID" \
--versioning-override-behavior auto_upgrade
If you want to move all your Workflows of a certain type to this new configuration, you can do it with this command:
temporal workflow update-options \
--query="WorkflowType='$WORKFLOW_TYPE'" \
--versioning-override-behavior auto_upgrade
You can also filter on a certain build ID to limit the number of Workflows you apply it to:
temporal workflow update-options \
--query="WorkflowType='$WORKFLOW_TYPE' AND TemporalWorkerDeploymentVersion='$TARGET_DEPLOYMENT:$OLD_VERSION'" \
--versioning-override-behavior auto_upgrade
When you change the behavior to Auto-Upgrade, the Workflow will resume work on the Workflow's Target Version. So if the Workflow's Target Version is different from the earlier Pinned Version, you should make sure you patch the Workflow code.