From 7318cdb122e9c7d52991037d5e652e7af1d6152b Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Mon, 2 Jun 2025 10:50:18 -0700 Subject: [PATCH 01/78] go versioning revisions --- docs/develop/go/versioning.mdx | 117 +++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 29 deletions(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 76d3e4c56f..250bf3d2af 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -19,17 +19,57 @@ tags: --- The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). -Because of that requirement, the Temporal Go SDK offers two dedicated versioning features. +If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +There are three primary Versioning methods supported by Temporal: -- [Workflow Patching APIs](#patching) -- [Worker Versioning](#worker-versioning) +- [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. +- [Branching with GetVersion](#getversion). This method works by adding branches to your code tied to specific revisions. In most other SDKs, it is called patching. +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). -## Temporal Go SDK Patching APIs {#patching} +## Workflow Type Versioning {#type-versioning} -The definition code of a Temporal Workflow must be deterministic because Temporal uses event sourcing to reconstruct the Workflow state by replaying the saved history event data on the Workflow definition code. -This means that any incompatible update to the Workflow Definition code could cause a non-deterministic issue if not handled correctly. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. -Because we design for potentially long running Workflows at scale, versioning with Temporal works differently. We explain more in this optional 30 minute introduction: [https://www.youtube.com/watch?v=kkP899WxgzY](https://www.youtube.com/watch?v=kkP899WxgzY) +For example, if you had made an incompatible change to the following Workflow Definition: + +```go +func PizzaWorkflow(ctx workflow.Context, order PizzaOrder) (OrderConfirmation, error) { + // implementation code omitted for this example +} +``` + +then you would change the code as follows: + +```go +func PizzaWorkflow(ctx workflow.Context, order PizzaOrder) (OrderConfirmation, error) { + // this function contains the original code +} + +func PizzaWorkflowV2(ctx workflow.Context, order PizzaOrder) (OrderConfirmation, error) { + // this function contains the updated code +} +``` + +You can use any name you like for the new function, so long as the first character remains uppercase (this is a requirement for any Workflow Definition, since it must use an exported function). +Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. + +You would then update the Worker configuration to register both Workflow Types: + +```go +w.RegisterWorkflow(pizza.PizzaWorkflow) +w.RegisterWorkflow(pizza.PizzaWorkflowV2) +``` + +The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. +The downside of this feature is that it does not use any Temporal platform features. +It requires you to duplicate code and to update any code and commands used to start the Workflow. +This can become impractical over time, depending on how you are providing configuration strings to your deployment. +This method also does not provide a way to introduce Versioning to any still-running Workflows -- it is essentially just a cutover. + +## Branching with GetVersion {#getversion} + +Branching with GetVersion essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. Consider the following Workflow Definition: @@ -143,17 +183,49 @@ if v == workflow.DefaultVersion { } ``` -Upgrading a Workflow is straightforward if you don't need to preserve your currently running Workflow Executions. -You can simply terminate all of the currently running Workflow Executions and suspend new ones from being created while you deploy the new version of your Workflow code, which does not use `GetVersion()`, and then resume Workflow creation. -However, that is often not the case, and you need to take care of the currently running Workflow Executions, so using `GetVersion()` to update your code is the method to use. +You can add multiple calls to `GetVersion` in a single Workflow. +This can become challenging to manage if you have many long-running Workflows, as you will wind up with many code branches over time. +To clean these up, you can gradually deprecate older versions. -However, if you want your currently running Workflows to proceed based on the current Workflow logic, but you want to ensure new Workflows are running on new logic, you can define your Workflow as a new `WorkflowType`, and change your start path (calls to `StartWorkflow()`) to start the new Workflow type. +### Deprecating Old versions + +You can safely remove support for older versions once you are certain that there are no longer any open Workflow Executions based on that version. You can use the following [List Filter](/list-filter) syntax for this (the 1 near the end of the last line represents the version number): + +``` +WorkflowType = "PizzaWorkflow" + AND ExecutionStatus = "Running" + AND TemporalChangeVersion="ChangedNotificationActivityType-1" +``` + +Since Workflow Executions that were started before `GetVersion` was added to the code won't have the associated Marker in their Event History, you'll need to use a different query to determine if any of those are still running: + +``` +WorkflowType = "PizzaWorkflow" + AND ExecutionStatus = "Running" + AND TemporalChangeVersion IS NULL +``` + +If you have found that there are no longer any open executions for the first two versions of the Workflow, for example, then you could remove support for them by changing the code as shown below: + +```go +version := GetVersion(ctx, "ChangedNotificationActivityType", 2, 3) +if version == 2 { + err = workflow.ExecuteActivity(ctx, SendTextMessage).Get(ctx, nil) +} else { + err = workflow.ExecuteActivity(ctx, SendTweet).Get(ctx, nil) +} +``` + +When workflow.GetVersion() is run for a new Workflow execution, it records a marker in the Workflow history so that all future calls to GetVersion() for this change ID — Step 1 in the example — on this Workflow execution will always return the given version number. + +GetVersion allows you to make changes to currently running Workflows. +It is a powerful method for introducing compatible changes without introducing non-determinism errors. +If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ## Sanity checking -The Temporal client SDK performs a sanity check to help prevent obvious incompatible changes. -The sanity check verifies whether a Command made in replay matches the event recorded in history, in the same order. -The Command is generated by calling any of the following methods: +The Temporal Go SDK performs a runtime sanity check to help prevent obvious incompatible changes. +Adding, removing, or reordering any of these methods without Versioning triggers the sanity check and results in a nondeterminism error: - workflow.ExecuteActivity() - workflow.ExecuteChildWorkflow() @@ -163,20 +235,7 @@ The Command is generated by calling any of the following methods: - workflow.SignalExternalWorkflow() - workflow.Sleep() -Adding, removing, or reordering any of the preceding methods triggers the sanity check and results in a nondeterminism error. - The sanity check does not perform a thorough check. For example, it does not check on the Activity's input arguments or the Timer duration. -If the check is enforced on every property, it becomes too restrictive and harder to maintain the Workflow code. -For example, if you move your Activity code from one package to another package, that move changes the `ActivityType`, which technically becomes a different Activity. -But we don't want to fail on that change, so we check only the function name part of the `ActivityType`. - -## How to use Worker Versioning in Go {#worker-versioning} - -Documentation for this feature is coming soon! - -For now, please join #safe-deploys in our [Community Slack](https://temporal.io/slack) to find the latest status and pre-release docs. - -If you were using a previous pre-release version of Worker Versioning, it's now deprecated. - -See [Legacy Worker Versioning](worker-versioning-legacy) if you still need those docs. +Each Temporal SDK implements these sanity checks differently, and they are not a complete check for non-deterministic changes. +Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. \ No newline at end of file From 91fff10c946d5a99419796d85956e948d7c05710 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Jun 2025 17:51:11 +0000 Subject: [PATCH 02/78] CI: Automatic .md and .mdx formatting --- docs/develop/go/versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 250bf3d2af..41a5eda4ed 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -238,4 +238,4 @@ Adding, removing, or reordering any of these methods without Versioning triggers The sanity check does not perform a thorough check. For example, it does not check on the Activity's input arguments or the Timer duration. Each Temporal SDK implements these sanity checks differently, and they are not a complete check for non-deterministic changes. -Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. \ No newline at end of file +Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. From 42c552b1c754571d97521b5cc8a4d8370ce72df9 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Mon, 2 Jun 2025 11:02:35 -0700 Subject: [PATCH 03/78] Update docs/develop/go/versioning.mdx Co-authored-by: angelazhou32 <141692465+angelazhou32@users.noreply.github.com> --- docs/develop/go/versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 41a5eda4ed..bfd40f2538 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -216,7 +216,7 @@ if version == 2 { } ``` -When workflow.GetVersion() is run for a new Workflow execution, it records a marker in the Workflow history so that all future calls to GetVersion() for this change ID — Step 1 in the example — on this Workflow execution will always return the given version number. +When `workflow.GetVersion()` is run for a new Workflow execution, it records a marker in the Workflow history so that all future calls to `GetVersion()` for this change ID — Step 1 in the example — on this Workflow execution will always return the given version number. GetVersion allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. From 12eb9336c9c10add1d0d3956741cad08680a6b97 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Mon, 2 Jun 2025 11:18:51 -0700 Subject: [PATCH 04/78] add more detail to sdk versioning page intro --- docs/develop/go/versioning.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index bfd40f2538..17b25df4ab 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -18,8 +18,10 @@ tags: - Temporal SDKs --- +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. There are three primary Versioning methods supported by Temporal: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. From 67897d3ea1ff1c68a39c93fca564ead785fa2348 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Mon, 2 Jun 2025 15:55:08 -0700 Subject: [PATCH 05/78] add revisions to ts and python --- docs/develop/go/versioning.mdx | 8 +- docs/develop/python/versioning.mdx | 108 +++++++----- docs/develop/typescript/versioning.mdx | 221 +++++++------------------ 3 files changed, 132 insertions(+), 205 deletions(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 17b25df4ab..d295d12f9a 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -64,14 +64,14 @@ w.RegisterWorkflow(pizza.PizzaWorkflowV2) ``` The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. -The downside of this feature is that it does not use any Temporal platform features. +The downside of this method is that it does not use any Temporal platform features. It requires you to duplicate code and to update any code and commands used to start the Workflow. This can become impractical over time, depending on how you are providing configuration strings to your deployment. -This method also does not provide a way to introduce Versioning to any still-running Workflows -- it is essentially just a cutover. +This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the `GetVersion` method. ## Branching with GetVersion {#getversion} -Branching with GetVersion essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Branching with `GetVersion` essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. Consider the following Workflow Definition: @@ -189,7 +189,7 @@ You can add multiple calls to `GetVersion` in a single Workflow. This can become challenging to manage if you have many long-running Workflows, as you will wind up with many code branches over time. To clean these up, you can gradually deprecate older versions. -### Deprecating Old versions +### Deprecating old versions You can safely remove support for older versions once you are certain that there are no longer any open Workflow Executions based on that version. You can use the following [List Filter](/list-filter) syntax for this (the 1 near the end of the last line represents the version number): diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index c16bcf57bc..70f3c344cd 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -30,26 +30,69 @@ tags: import { CaptionedImage } from '@site/src/components'; -The definition code of a Temporal Workflow must be deterministic because Temporal uses event sourcing -to reconstruct the Workflow state by replaying the saved history event data on the Workflow -definition code. This means that any incompatible update to the Workflow Definition code could cause -a non-deterministic issue if not handled correctly. +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. +The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). +If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. +There are three primary Versioning methods supported by Temporal: -## Introduction to Versioning +- [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. +- [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). -Because we design for potentially long running Workflows at scale, versioning with Temporal works differently. We explain more in this optional 30 minute introduction: [https://www.youtube.com/watch?v=kkP899WxgzY](https://www.youtube.com/watch?v=kkP899WxgzY) +## Workflow Type Versioning {#type-versioning} -## How to use the Python SDK Patching API {#python-sdk-patching-api} +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. -In principle, the Python SDK's patching mechanism operates similarly to other SDKs in a "feature-flag" fashion. However, the "versioning" API now uses the concept of "patching in" code. +For example, if you had made an incompatible change to the following Workflow Definition: -To understand this, you can break it down into three steps, which reflect three stages of migration: +```python +@workflow.defn(name="PizzaWorkflow") +class PizzaWorkflow: + @workflow.run + async def run(self, name: str) -> str: + # implementation code omitted for this example +``` -- Running `pre_patch_activity` code while concurrently patching in `post_patch_activity`. -- Running `post_patch_activity` code with deprecation markers for `my-patch` patches. -- Running only the `post_patch_activity` code. +then you would change the code as follows: -Let's walk through this process in sequence. +```python +@workflow.defn(name="PizzaWorkflow") +class PizzaWorkflow: + @workflow.run + async def run(self, name: str) -> str: + # this function contains the original code + +@workflow.defn(name="PizzaWorkflowV2") +class PizzaWorkflowV2: + @workflow.run + async def run(self, name: str) -> str: + # this function contains the updated code +``` + +You can use any name you like for the new function, so long as the first character remains uppercase (this is a requirement for any Workflow Definition, since it must use an exported function). +Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. + +You would then update the Worker configuration to register both Workflow Types: + +```python +worker = Worker( + client, + task_queue="your-task-queue", + workflows=[PizzaWorkflow, PizzaWorkflowV2], +) +``` + +The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. +The downside of this method is that it does not use any Temporal platform features. +It requires you to duplicate code and to update any code and commands used to start the Workflow. +This can become impractical over time, depending on how you are providing configuration strings to your deployment. +This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the Patching method. + +## Versioning with Patching {#patching} + +Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. Suppose you have an initial Workflow version called `pre_patch_activity`: @@ -105,27 +148,21 @@ class MyWorkflow: ) ``` -**Problem: You cannot deploy `post_patch_activity` directly until you're certain there are no more running Workflows created using the `pre_patch_activity` code, otherwise you are likely to cause a nondeterminism error.** - +The problem is that you cannot deploy `post_patch_activity` directly until you're certain there are no more running Workflows created using the `pre_patch_activity` code, otherwise you are likely to cause a nondeterminism error. Instead, you'll need to deploy `post_patched_activity` and use the [patched](https://python.temporal.io/temporalio.workflow.html#patched) function to determine which version of the code to execute. -Implementing patching involves three steps: +Patching is a three-step process: -1. Use [patched](https://python.temporal.io/temporalio.workflow.html#patched) to patch in new code and run it alongside the old code. -2. Remove the old code and apply [deprecate_patch](https://python.temporal.io/temporalio.workflow.html#deprecate_patch). -3. Once you're confident that all old Workflows have finished executing, remove `deprecate_patch`. +1. Patch in any new, updated code using the `patched()` function. Run the new patched code alongside old code. +2. Remove old code and use `deprecate_patch()` to mark a particular patch as deprecated. +3. Once there are no longer any open Worklow Executions of the previous version of the code, remove `deprecate_patch()`. +Let's walk through this process in sequence. ### Patching in new code {#using-patched-for-workflow-history-markers} Using `patched` inserts a marker into the Workflow History. - - - -During replay, if a Worker encounters a history with that marker, it will fail the Workflow task when the Workflow code doesn't produce the same patch marker (in this case, `my-patch`). This ensures you can safely deploy code from `post_patch_activity` as a "feature flag" alongside the original version (`pre_patch_activity`). +During Replay, if a Worker encounters a history with that marker, it will fail the Workflow task when the Workflow code doesn't produce the same patch marker (in this case, `my-patch`). +This ensures you can safely deploy code from `post_patch_activity` as a "feature flag" alongside the original version (`pre_patch_activity`).
@@ -152,7 +189,7 @@ class MyWorkflow: ) ``` -### Understanding deprecated Patches in the Python SDK {#deprecated-patches} +### Deprecating patches {#deprecated-patches} After ensuring that all Workflows started with `pre_patch_activity` code have finished, you can [deprecate the patch](https://python.temporal.io/temporalio.workflow.html#deprecate_patch). @@ -182,9 +219,9 @@ class MyWorkflow: ) ``` -### Safe Deployment of post_patch_activity {#deploy-new-code} +### Removing a patch {#deploy-new-code} -Once you're sure that you will no longer need to Query or Replay any of your pre-patch Workflows, you can then safely deploy Workers that no longer use either the `patched()` or `deprecate_patch()` calls: +Once you're sure that you will no longer need to [Query](/develop/python/message-passing#send-query) or Replay any of your pre-patch Workflows, you can then safely deploy Workers that no longer use either the `patched()` or `deprecate_patch()` calls:
@@ -205,12 +242,5 @@ class MyWorkflow: ) ``` -## How to use Worker Versioning in Python {#worker-versioning} - -This feature is coming soon! - -For now, please join #safe-deploys in our [Community Slack](https://temporal.io/slack) to find the latest status and pre-release docs. - -If you were using a previous pre-release version of Worker Versioning, it's now deprecated. - -See [Legacy Worker Versioning](worker-versioning-legacy) if you still need those docs. +Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). \ No newline at end of file diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index faf9f7af49..4e33965047 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -3,7 +3,7 @@ id: versioning title: Versioning - TypeScript SDK sidebar_label: Versioning slug: /develop/typescript/versioning -description: Temporal TypeScript SDK ensures deterministic Workflow code with versioning features like Workflow Patching APIs, Worker Build IDs, and Workflow migration strategies. Learn more with our 30-min video intro. +description: Temporal TypeScript SDK ensures deterministic Workflow code with versioning features like Workflow Patching APIs, Worker Build IDs, and Workflow migration strategies. toc_max_heading_level: 4 keywords: - patching @@ -20,128 +20,64 @@ tags: import { CaptionedImage } from '@site/src/components'; +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). -Because of that requirement, the Temporal TypeScript SDK offers two dedicated versioning features. +If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. +There are three primary Versioning methods supported by Temporal: -- [Workflow Patching APIs](#patching) -- [Worker Versioning](#worker-versioning) +- [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. +- [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). -### Alternatives +## Workflow Type Versioning {#type-versioning} -Before you explore dedicated versioning features, check whether your needs can be addressed in other ways: +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. -- [Version Task Queue](#version-task-queue) -- [Version Workflow Name](#version-workflow-name) +For example, if you had made an incompatible change to the following Workflow Definition: -Both options mean that Workflows running `v1` code will never migrate to `v2` code; they will run `v1` code to completion. -If you would like to update Workflows running `v1` _while they are still running,_ you [might need to "patch in" code](#do-i-need-to-patch). - -#### Version Task Queue - -If you're currently running v1 Workflow code on Workers that poll on `queue1`, you can run v2 Workflow code on Workers that poll on `queue2`: - -1. Leave some Workers running your v1 `Workflow`, on the `queue1` Task Queue. -1. Change your `Workflow` code and spin up new Workers that are polling a `queue2` Task Queue. -1. Cut over your Clients to only call `Workflow` on `queue2` from now on. -1. Remove your v1 Workers when all the v1 Workflows have completed. - -#### Version Workflow Name - -Although versioning the Task Queue is usually easier, we can also create a new version of a Workflow by copying it and changing its name: - -1. Copy the `Workflow1` code to a `Workflow2` function and change what you need. -1. Register `Workflow2` in your Workers alongside `Workflow1`. -1. Cut over your Clients to only call `Workflow2` from now on. -1. Remove `Workflow1` code when none of them are running anymore. - -## How to patch Workflow code in TypeScript {#patching} - -The TypeScript SDK Patching API lets you change Workflow Definitions without causing [non-deterministic behavior](/workflow-definition#non-deterministic-change) in current long-running Workflows. - -### Do I need to Patch? - -You may need to patch if: - -- You want to change the remaining logic of a Workflow while it is still running -- If your new logic can result in a different execution path - -This added `sleep()` can result in a different execution path: - -```ts -// from v1 -export async function yourWorkflow(value: number): Promise { - await runActivity(); - return 7; -} - -// to v2 -export async function yourWorkflow(value: number): Promise { - await sleep('1 day'); - - await runActivity(); - return 7; +```typescript +function pizzaWorkflow(order: PizzaOrder): Promise { + // implementation code omitted for this example } ``` -If v2 is deployed while there's a Workflow on the `runActivity` step, when the Activity completes, the Worker will try to replay the Workflow (in order to continue Workflow execution), notice that the sleep command is called and doesn't match with the Workflow's Event History, and throw a non-determinism error. +then you would change the code as follows: -Adding a Signal Handler for a Signal type that has never been sent before does not need patching: - -```ts -// from v1 -export async function yourWorkflow(value: number): Promise { - await sleep('1 days'); - return value; +```typescript +function pizzaWorkflow(order: PizzaOrder): Promise { + // this function contains the original code } -// to v2 -const updateValueSignal = defineSignal<[number]>('updateValue'); - -export async function yourWorkflow(value: number): Promise { - setHandler(updateValueSignal, (newValue) => (value = newValue)); - - await sleep('1 days'); - return value; +function pizzaWorkflowV2(order: PizzaOrder): Promise { + // this function contains the updated code } ``` -### Migrating Workflows in Patches - -Workflow code has to be [deterministic](/workflow-definition#deterministic-constraints) by taking the same code path when replaying History Events. -Any Workflow code change that affects the order in which commands are generated breaks this assumption. - -So we have to keep both the old and new code when migrating Workflows while they are still running: - -- When replaying, use the original code version that generated the ongoing event history. -- When executing a new code path, always execute the - new code. +You can use any name you like for the new function, so long as the first character remains uppercase (this is a requirement for any Workflow Definition, since it must use an exported function). +Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. -
- - 30 Min Video: Introduction to Versioning - +You would then update the Worker configuration to register both Workflow Types: -Because we design for potentially long-running Workflows at scale, versioning with Temporal works differently than with other Workflow systems. -We explain more in this optional 30 minute introduction: [https://www.youtube.com/watch?v=kkP899WxgzY](https://www.youtube.com/watch?v=kkP899WxgzY) - -
- -### TypeScript SDK Patching API - -In principle, the TypeScript SDK's patching mechanism works in a similar "feature-flag" fashion to the other SDKs; however, the "versioning" API has been updated to a notion of "patching in" code. -There are three steps to this reflecting three stages of migration: - -- Running v1 code with vFinal patched in concurrently -- Running vFinal code with deprecation markers for vFinal patches -- Running "just" vFinal code. +```typescript +const worker = await Worker.create({ + workflowsPath: require.resolve("./workflows"), + //other configurations +}); +``` -This is best explained in sequence (click through to follow along using our SDK sample). +The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. +The downside of this method is that it does not use any Temporal platform features. +It requires you to duplicate code and to update any code and commands used to start the Workflow. +This can become impractical over time, depending on how you are providing configuration strings to your deployment. +This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the Patching method. -Given an initial Workflow version `v1`: +## Versioning with Patching {#patching} - +Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. -[patching-api/src/workflows-v1.ts](https://github.com/temporalio/samples-typescript/blob/main/patching-api/src/workflows-v1.ts) +Suppose you have an initial Workflow that runs `activityA`: ```ts // v1 @@ -152,14 +88,7 @@ export async function myWorkflow(): Promise { } ``` - - -We decide to update our code and run `activityB` instead. -This is our desired end state, `vFinal`. - - - -[patching-api/src/workflows-vFinal.ts](https://github.com/temporalio/samples-typescript/blob/main/patching-api/src/workflows-vFinal.ts) +Now, you want to update your code to run `activityB` instead. This represents your desired end state. ```ts // vFinal @@ -169,33 +98,21 @@ export async function myWorkflow(): Promise { } ``` - - -**Problem: We cannot directly deploy `vFinal` until we know for sure there are no more running Workflows created using `v1` code.** - -Instead we must deploy `v2` (below) and use the [`patched`](https://typescript.temporal.io/api/namespaces/workflow#patched) function to check which version of the code should be executed. +The problem is that you cannot deploy this `vFinal` revision directly until you're certain there are no more running Workflows created using the `v1` code, otherwise you are likely to cause a nondeterminism error. +Instead, you'll need to use the [`patched`](https://typescript.temporal.io/api/namespaces/workflow#patched) function to check which version of the code should be executed. Patching is a three-step process: -1. Patch in new code with `patched` and run it alongside old code -2. Remove old code and `deprecatePatch` -3. When you are sure all old Workflows are done executing, remove `deprecatePatch` - -#### Step 1: Patch in new code - -`patched` inserts a marker into the Workflow history. - - +1. Patch in any new, updated code using the `patched()` function. Run the new patched code alongside old code. +2. Remove old code and use `deprecatePatch()` to mark a particular patch as deprecated. +3. Once there are no longer any open Worklow Executions of the previous version of the code, remove `deprecatePatch()`. +Let's walk through this process in sequence. -During replay, when a Worker picks up a history with that marker it will fail the Workflow task when running Workflow code that does not emit the same patch marker (in this case `your-change-id`); therefore it is safe to deploy code from `v2` in a "feature flag" alongside the original version (`v1`). +### Patching in new code - - -[patching-api/src/workflows-v2.ts](https://github.com/temporalio/samples-typescript/blob/main/patching-api/src/workflows-v2.ts) +Using `patched` inserts a marker into the Workflow History. +During Replay, if a Worker encounters a history with that marker, it will fail the Workflow task when the Workflow code doesn't produce the same patch marker (in this case `your-change-id`). +This ensures you can safely deploy code from `v2` as a "feature flag" alongside the original version (`v1`). ```ts // v2 @@ -211,21 +128,15 @@ export async function myWorkflow(): Promise { } } ``` +### Deprecating patches {#deprecated-patches} - - -#### Step 2: Deprecate patch +After ensuring that all Workflows started with `v1` code have finished, you can [deprecate the patch](https://typescript.temporal.io/api/namespaces/workflow#deprecatepatch). -When we know that all Workflows started with `v1` code have completed, we can [deprecate the patch](https://typescript.temporal.io/api/namespaces/workflow#deprecatepatch). -Deprecated patches bridge between `v2` and `vFinal` (the end result). -They work similarly to regular patches by recording a marker in the Workflow history. +Once you're confident that your Workflows are no longer running the pre-patch code paths, you can deploy your code with `deprecatePatch()`. +These Workers will be running the most up-to-date version of the Workflow code, which no longer requires the patch. +The `deprecatePatch()` function works similarly to the `patched()` function by recording a marker in the Workflow history. This marker does not fail replay when Workflow code does not emit it. - -If while we're deploying `v3` (below) there are still live Workers running `v2` code and those Workers pick up Workflow histories generated by `v3`, they will safely use the patched branch. - - - -[patching-api/src/workflows-v3.ts](https://github.com/temporalio/samples-typescript/blob/main/patching-api/src/workflows-v3.ts) +Deprecated patches serve as a bridge between the pre-patch code paths and the post-patch code paths, and are useful for avoiding errors resulting from patched code paths in your Workflow history. ```ts // v3 @@ -238,23 +149,9 @@ export async function myWorkflow(): Promise { } ``` - - -#### Step 3: Solely deploy new code - -`vFinal` is safe to deploy once all `v2` or earlier Workflows are complete due to the assertion mentioned above. - -### Upgrading Workflow dependencies - -Upgrading Workflow dependencies (such as ones installed into `node_modules`) _might_ break determinism in unpredictable ways. -We recommended using a lock file (`package-lock.json` or `yarn.lock`) to fix Workflow dependency versions and gain control of when they're updated. - -## How to use Worker Versioning in TypeScript {#worker-versioning} - -This feature is coming soon! - -For now, please join #safe-deploys in our [Community Slack](https://temporal.io/slack) to find the latest status and pre-release docs. +### Removing a patch {#deploy-new-code} -If you were using a previous pre-release version of Worker Versioning, it's now deprecated. +Once you're sure that you will no longer need to [Query](/develop/typescript/message-passing#send-query) or Replay any of your pre-patch Workflows, you can then safely deploy Workers that no longer use either the `patched()` or `deprecatePatch()` calls: -See [Legacy Worker Versioning](worker-versioning-legacy) if you still need those docs. +Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). \ No newline at end of file From b22a0836f1f86471b720d29f2abacadf52f2642c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 2 Jun 2025 22:56:02 +0000 Subject: [PATCH 06/78] CI: Automatic .md and .mdx formatting --- docs/develop/python/versioning.mdx | 4 ++-- docs/develop/typescript/versioning.mdx | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 70f3c344cd..6b0b385094 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -156,7 +156,7 @@ Patching is a three-step process: 1. Patch in any new, updated code using the `patched()` function. Run the new patched code alongside old code. 2. Remove old code and use `deprecate_patch()` to mark a particular patch as deprecated. 3. Once there are no longer any open Worklow Executions of the previous version of the code, remove `deprecate_patch()`. -Let's walk through this process in sequence. + Let's walk through this process in sequence. ### Patching in new code {#using-patched-for-workflow-history-markers} @@ -243,4 +243,4 @@ class MyWorkflow: ``` Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). \ No newline at end of file +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index 4e33965047..9cef49b261 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -62,8 +62,8 @@ You would then update the Worker configuration to register both Workflow Types: ```typescript const worker = await Worker.create({ - workflowsPath: require.resolve("./workflows"), - //other configurations + workflowsPath: require.resolve('./workflows'), + // other configurations }); ``` @@ -106,7 +106,7 @@ Patching is a three-step process: 1. Patch in any new, updated code using the `patched()` function. Run the new patched code alongside old code. 2. Remove old code and use `deprecatePatch()` to mark a particular patch as deprecated. 3. Once there are no longer any open Worklow Executions of the previous version of the code, remove `deprecatePatch()`. -Let's walk through this process in sequence. + Let's walk through this process in sequence. ### Patching in new code @@ -128,6 +128,7 @@ export async function myWorkflow(): Promise { } } ``` + ### Deprecating patches {#deprecated-patches} After ensuring that all Workflows started with `v1` code have finished, you can [deprecate the patch](https://typescript.temporal.io/api/namespaces/workflow#deprecatepatch). @@ -154,4 +155,4 @@ export async function myWorkflow(): Promise { Once you're sure that you will no longer need to [Query](/develop/typescript/message-passing#send-query) or Replay any of your pre-patch Workflows, you can then safely deploy Workers that no longer use either the `patched()` or `deprecatePatch()` calls: Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). \ No newline at end of file +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). From 65c520779db8556f9392117bbda26af8eab96373 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Tue, 3 Jun 2025 17:02:01 -0700 Subject: [PATCH 07/78] rewrite java, copyedit others --- docs/develop/go/versioning.mdx | 18 ++-- docs/develop/java/versioning.mdx | 144 +++++++++++++++++-------- docs/develop/python/versioning.mdx | 8 +- docs/develop/typescript/versioning.mdx | 8 +- 4 files changed, 121 insertions(+), 57 deletions(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index d295d12f9a..52795e4be3 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -18,7 +18,7 @@ tags: - Temporal SDKs --- -Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -93,12 +93,13 @@ func YourWorkflow(ctx workflow.Context, data string) (string, error) { } ``` -Now let's say we replaced ActivityA with ActivityC and deployed the updated code. -If an existing Workflow Execution was started by the original version of the Workflow code, where ActivityA had already completed and the result was recorded to history, the new version of the Workflow code picks up that Workflow Execution and tries to resume from there. -However, the Workflow will fail because the new code expects a result for ActivityC from the history data, but instead it gets the result for ActivityA. -This causes the Workflow to fail on the nondeterminism error. +Now let's say we replaced `ActivityA` with `ActivityC` and deployed the updated code. -Thus we use `workflow.GetVersion().` +Imagine you want to revise this Workflow by adding another Activity to calculate a file checksum. +If an existing Workflow Execution was started by the original version of the Workflow code, where `ActivityA` was run, and then resumed running on a new Worker where it was replaced with `ActivityC`, the server side Event History would be out of sync. +This would cause the Workflow to fail with a nondeterminism error. + +Thus we use `workflow.GetVersion()`: ```go var err error @@ -117,7 +118,7 @@ err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2) return result2, err ``` -When `workflow.GetVersion()` is run for the new Workflow Execution, it records a marker in the Workflow history so that all future calls to `GetVersion` for this change Id—`Step 1` in the example—on this Workflow Execution will always return the given version number, which is `1` in the example. +When `workflow.GetVersion()` is run for the new Workflow Execution, it records a marker in the Event History so that all future calls to `GetVersion` for this change Id — `Step 1` in the example — on this Workflow Execution will always return the given version number, which is `1` in the example. If you make an additional change, such as replacing ActivityC with ActivityD, you need to add some additional code: @@ -138,8 +139,7 @@ A Workflow that has already passed this `GetVersion()` call before it was introd A Workflow that was run with `maxSupported` set to 1 returns 1. New Workflows return 2. -After you are sure that all of the Workflow Executions prior to version 1 have completed, you can remove the code for that version. -It should now look like the following: +After you are sure that all of the Workflow Executions prior to version 1 have completed, you can remove the code for that version: ```go v := workflow.GetVersion(ctx, "Step1", 1, 2) diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index a0ec14387d..afc3c4b83c 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -19,16 +19,88 @@ tags: - Temporal SDKs --- +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). -Because of that requirement, the Temporal Java SDK offers two dedicated versioning features: +If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. +There are three primary Versioning methods supported by Temporal: -- [Workflow Patching APIs](#patching) -- [Worker Versioning](#worker-versioning) +- [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. +- [Branching with GetVersion](#getversion). This method works by adding branches to your code tied to specific revisions. In most other SDKs, it is called patching. +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). -## How to patch Workflows in Java {#patching} +## Workflow Type Versioning {#type-versioning} -Use the `Workflow.getVersion` function to return a version of the code that should be executed and then use the returned value to pick a correct branch. -Let's look at an example. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. + +For example, if you had made an incompatible change to the following Workflow Definition: + +```java +import io.temporal.workflow.WorkflowInterface; +import io.temporal.workflow.WorkflowMethod; + +@WorkflowInterface +public interface PizzaWorkflow { + + @WorkflowMethod + public OrderConfirmation pizzaWorkflow(PizzaOrder order); +} + +public class PizzaWorkflowImpl{ + + @Override + public OrderConfirmation pizzaWorkflow(PizzaOrder order){ + // implementation code omitted for this example + } +} +``` + +then you would create a separate interface and class as follows: + +```java +import io.temporal.workflow.WorkflowInterface; +import io.temporal.workflow.WorkflowMethod; + +@WorkflowInterface +public interface PizzaWorkflowV2 { + + @WorkflowMethod + public OrderConfirmation pizzaWorkflow(PizzaOrder order); +} + +public class PizzaWorkflowImplV2 implements PizzaWorkflowV2{ + + @Override + public OrderConfirmation pizzaWorkflow(PizzaOrder order){ + // implementation code omitted for this example + } +} +``` + +It is necessary to create a separate interface because a Workflow Interface can only have one Workflow Method. + +You can use any name you like for the new function. +Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. + +You would then update the Worker configuration to register both Workflow Types: + +```java +worker.registerWorkflowImplementationTypes(PizzaWorkflowImpl.class); +worker.registerWorkflowImplementationTypes(PizzaWorkflowImplV2.class); +``` + +The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. +The downside of this method is that it does not use any Temporal platform features. +It requires you to duplicate code and to update any code and commands used to start the Workflow. +This can become impractical over time, depending on how you are providing configuration strings to your deployment. +This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the `GetVersion` method. + +## Branching with GetVersion {#getversion} + +Branching with `Workflow.getVersion` essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. + +Consider the following Workflow Definition: ```java public void processFile(Arguments args) { @@ -49,8 +121,11 @@ public void processFile(Arguments args) { } ``` -Now we decide to calculate the processed file checksum and pass it to upload. -The correct way to implement this change is: +Imagine you want to revise this Workflow by adding another Activity to calculate a file checksum. +If an existing Workflow Execution was started by the original version of the Workflow code, where there was no `calculateChecksum()` Activity, and then resumed running on a new Worker where this Activity had been added, the server side Event History would be out of sync. +This would cause the Workflow to fail with a nondeterminism error. + +Thus we use `workflow.GetVersion()`: ```java public void processFile(Arguments args) { @@ -78,7 +153,9 @@ public void processFile(Arguments args) { } ``` -Later, when all Workflows that use the old version are completed, the old branch can be removed. +When `workflow.GetVersion()` is run for the new Workflow Execution, it records a marker in the Event History so that all future calls to `GetVersion` for this change id — `checksumAdded` in the example — on this Workflow Execution will always return the given version number, which is `1` in the example. + +After you are sure that all of the Workflow Executions prior to version 1 have completed, you can remove the code for that version. ```java public void processFile(Arguments args) { @@ -105,18 +182,12 @@ public void processFile(Arguments args) { } ``` -The Id that is passed to the `getVersion` call identifies the change. Each change is expected to have its own Id. But if -a change spawns multiple places in the Workflow code and the new code should be either executed in all of them or -in none of them, then they have to share the Id. - ### Adding Support for Versioned Workflow Visibility in the Event History -In other Temporal SDKs, when you invoke the Patching API, the SDK records an -`UpsertWorkflowSearchAttribute` Event in the history. This adds support -for a custom query parameter in the web UI named `TemporalChangeVersion` that -allows you to filter Workflows based on their version. Unfortunately, the Java -SDK doesn't currently support the automatic adding of this attribute, so you'll -have to do it manually instead. +In other Temporal SDKs, when you invoke `getVersion` or the patching API, the SDK records an +`UpsertWorkflowSearchAttribute` Event in the history. +This adds support for a custom query parameter in the web UI named `TemporalChangeVersion` that allows you to filter Workflows based on their version. +The Java SDK does not automatically add this attribute, so you'll likely want to do it manually. Within your Workflow Implementation code you'll need to perform the following steps: @@ -136,13 +207,7 @@ public static final SearchAttributeKey> TEMPORAL_CHANGE_VERSION = S #### Set the Search Attribute using `upsert` -You will set this attribute when you make the call to `getVersion`. It is important -to set this value as soon as possible after the `getVersion` call so you can be -able to search for the Workflow as soon as possible. For example, if you set -the attribute at the end of your Workflow, you'd have to wait until the very end -of the execution to be able to identify what version this is. As you'll read later, -being able to know how many Workflows of a specific version are still running is -important when you are trying to deprecate older Workflow versions and their workers. +You should set this attribute when you make the call to `getVersion`. ```java int version = Workflow.getVersion("MovedThankYouAfterLoop", Workflow.DEFAULT_VERSION, 1); @@ -153,19 +218,13 @@ if (version != Workflow.DEFAULT_VERSION) { } ``` -You should only set the attribute on new versions. Setting the attribute on the -default version will cause a non-deterministic error. +You should only set the attribute on new versions. #### Setting Attributes for Multiple `getVersion` Calls -The code in the previous section works well for code that only has one call to -`getVersion`. However, you may encounter situations where you have to have -multiple calls to `getVersion` to handle multiple independent changes to your -Workflow. If you were to use the code above you'd overwrite all but the last -call to `getVersion` in your event history. Therefore you should create -a list of all the version changes and then set the attribute value. - -Example: +The code in the previous section works well for code that only has one call to `getVersion()`. +However, you may encounter situations where you have to have multiple calls to `getVersion()` to handle multiple independent changes to your Workflow. +In this case, you should create a list of all the version changes and then set the attribute value: ```java List list = new ArrayList(); @@ -180,12 +239,9 @@ if (versionTwo != Workflow.DEFAULT_VERSION) { Workflow.upsertTypedSearchAttributes(Constants.TEMPORAL_CHANGE_VERSION.valueSet(list)); ``` -## How to use Worker Versioning in Java {#worker-versioning} - -This feature is coming soon! - -For now, please join #safe-deploys in our [Community Slack](https://temporal.io/slack) to find the latest status and pre-release docs. - -If you were using a previous pre-release version of Worker Versioning, it's now deprecated. +GetVersion allows you to make changes to currently running Workflows. +It is a powerful method for introducing compatible changes without introducing non-determinism errors. +If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). -See [Legacy Worker Versioning](worker-versioning-legacy) if you still need those docs. +Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 6b0b385094..87a1e0d1f1 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -30,7 +30,7 @@ tags: import { CaptionedImage } from '@site/src/components'; -Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -71,7 +71,7 @@ class PizzaWorkflowV2: # this function contains the updated code ``` -You can use any name you like for the new function, so long as the first character remains uppercase (this is a requirement for any Workflow Definition, since it must use an exported function). +You can use any name you like for the new function. Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. You would then update the Worker configuration to register both Workflow Types: @@ -242,5 +242,9 @@ class MyWorkflow: ) ``` +Patching allows you to make changes to currently running Workflows. +It is a powerful method for introducing compatible changes without introducing non-determinism errors. +If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index 9cef49b261..96517d0367 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -20,7 +20,7 @@ tags: import { CaptionedImage } from '@site/src/components'; -Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need major changes to a Workflow Definition, even while a particular Workflow Execution is in progress. +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -55,7 +55,7 @@ function pizzaWorkflowV2(order: PizzaOrder): Promise { } ``` -You can use any name you like for the new function, so long as the first character remains uppercase (this is a requirement for any Workflow Definition, since it must use an exported function). +You can use any name you like for the new function. Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. You would then update the Worker configuration to register both Workflow Types: @@ -154,5 +154,9 @@ export async function myWorkflow(): Promise { Once you're sure that you will no longer need to [Query](/develop/typescript/message-passing#send-query) or Replay any of your pre-patch Workflows, you can then safely deploy Workers that no longer use either the `patched()` or `deprecatePatch()` calls: +Patching allows you to make changes to currently running Workflows. +It is a powerful method for introducing compatible changes without introducing non-determinism errors. +If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). From d7484127ae6e5883c00c580957687df74eecdab3 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 09:08:29 -0700 Subject: [PATCH 08/78] add dotnet revisions --- docs/develop/dotnet/versioning.mdx | 98 +++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index 8b02cb5e54..5f759039d9 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -27,40 +27,74 @@ tags: - Patching --- -This page shows how to do the following: +import { CaptionedImage } from '@site/src/components'; -- [Use the .NET SDK Patching API](#dotnet-sdk-patching-api) -- [Patching in new code](#using-patched-for-workflow-history-markers) -- [Understanding deprecated Patches in the .NET SDK](#deprecated-patches) -- [Safe Deployment of PostPatchActivity](#deploy-postpatchactivity) +Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. +The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). +If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. +With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. +There are three primary Versioning methods supported by Temporal: -## Introduction to Versioning +- [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. +- [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). -Because we design for potentially long running Workflows at scale, versioning with Temporal works differently. We explain more in this optional 30 minute introduction: +## Workflow Type Versioning {#type-versioning} -
- -
+Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. -## Use the .NET SDK Patching API {#dotnet-sdk-patching-api} +For example, if you had made an incompatible change to the following Workflow Definition: -**How to use the .NET SDK Patching API using the Temporal .NET SDK** +```csharp +[Workflow] +public class SayHelloWorkflow +{ + [WorkflowRun] + # implementation code omitted for this example +} +``` -In principle, the .NET SDK's patching mechanism operates similarly to other SDKs in a "feature-flag" fashion. However, the "versioning" API now uses the concept of "patching in" code. +then you would change the code as follows: -To understand this, you can break it down into three steps, which reflect three stages of migration: +```csharp +[Workflow] +public class SayHelloWorkflow +{ + [WorkflowRun] + # this function contains the original code +} + +[Workflow] +public class SayHelloWorkflowV2 +{ + [WorkflowRun] + # this function contains the updated code +} +``` + +You can use any name you like for the new function. +Using some type of version identifier, such as V2 in this example, will make it easier to identify the change. + +You would then update the Worker configuration to register both Workflow Types: + +```csharp +using var worker = new TemporalWorker( + client, + new TemporalWorkerOptions("greeting-tasks") + .AddWorkflow() + .AddWorkflow()); +``` + +The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. +The downside of this method is that it does not use any Temporal platform features. +It requires you to duplicate code and to update any code and commands used to start the Workflow. +This can become impractical over time, depending on how you are providing configuration strings to your deployment. +This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the Patching method. -- Running `PrePatchActivity` code while concurrently patching in `PostPatchActivity`. -- Running `PostPatchActivity` code with deprecation markers for `my-patch` patches. -- Running only the `PostPatchActivity` code. +## Versioning with Patching {#patching} -Let's walk through this process in sequence. +Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. Suppose you have an initial Workflow version called `PrePatchActivity`: @@ -98,11 +132,10 @@ public class MyWorkflow } ``` -**Problem: You cannot deploy `PostPatchActivity` directly until you're certain there are no more running Workflows created using the `PrePatchActivity` code, otherwise you are likely to cause a nondeterminism error.** - +The problem is that you cannot deploy `PostPatchActivity` directly until you're certain there are no more running Workflows created using the `PrePatchActivity` code, otherwise you are likely to cause a nondeterminism error. Instead, you'll need to deploy `PostPatchActivity` and use the [Patched](https://dotnet.temporal.io/api/Temporalio.Workflows.Workflow.html#Temporalio_Workflows_Workflow_Patched_System_String_) method to determine which version of the code to execute. -Implementing patching involves three steps: +Patching is a three step process: 1. Use [Patched](https://dotnet.temporal.io/api/Temporalio.Workflows.Workflow.html#Temporalio_Workflows_Workflow_Patched_System_String_) to patch in new code and run it alongside the old code. 2. Remove the old code and apply [DeprecatePatch](https://dotnet.temporal.io/api/Temporalio.Workflows.Workflow.html#Temporalio_Workflows_Workflow_DeprecatePatch_System_String_). @@ -139,7 +172,7 @@ public class MyWorkflow } ``` -### Understanding deprecated Patches in the .NET SDK {#deprecated-patches} +### Deprecating patches {#deprecated-patches} After ensuring that all Workflows started with `PrePatchActivity` code have finished, you can [deprecate the patch](https://dotnet.temporal.io/api/Temporalio.Workflows.Workflow.html#Temporalio_Workflows_Workflow_DeprecatePatch_System_String_). @@ -164,7 +197,7 @@ public class MyWorkflow } ``` -### Safe Deployment of PostPatchActivity {#deploy-postpatchactivity} +### Removing a patch {#deploy-postpatchactivity} You can safely deploy `PostPatchActivity` once all Workflows labeled my-patch or earlier are finished, based on the previously mentioned assertion. @@ -183,3 +216,10 @@ public class MyWorkflow } } ``` + +Patching allows you to make changes to currently running Workflows. +It is a powerful method for introducing compatible changes without introducing non-determinism errors. +If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. +To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay-test). From 1913777b99439dafca9c1ba95b1034849016f1af Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 10:05:50 -0700 Subject: [PATCH 09/78] surgery on other parts of docs mentioning worker versioning --- docs/develop/determinism.mdx | 32 ++++++ docs/develop/safe-deployments.mdx | 100 ------------------ .../encyclopedia/worker-versioning-legacy.mdx | 6 +- .../workers/worker-deployments.mdx | 85 --------------- .../workers/worker-versioning.mdx | 29 ----- .../workflow/workflow-definition.mdx | 23 ++-- docs/production-deployment/index.mdx | 5 + sidebars.js | 17 ++- vercel.json | 15 +++ 9 files changed, 77 insertions(+), 235 deletions(-) create mode 100644 docs/develop/determinism.mdx delete mode 100644 docs/develop/safe-deployments.mdx delete mode 100644 docs/encyclopedia/workers/worker-deployments.mdx delete mode 100644 docs/encyclopedia/workers/worker-versioning.mdx diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx new file mode 100644 index 0000000000..45bf35bf43 --- /dev/null +++ b/docs/develop/determinism.mdx @@ -0,0 +1,32 @@ +--- +id: determinism +title: Making revisions to Workflow code +description: Safely deploy changes to existing Workflow code by validating first for determinism errors before deploying to production. +sidebar_label: Determinism +toc_max_heading_level: 3 +tags: + - Workflows + - Deployment + - Replay +--- + +Making revisions to existing Workflow code can be challenging. Your Workflow code must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints). This means your changes to that code have to be as well. Changes to your Workflow code that qualify as non-deterministic need to be protected by either using the [Versioning APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code. + +## Use Replay Testing before and during your deployments + +The best way to verify that your code won't cause non-determinism errors once deployed is to make use of [replay testing](https://docs.temporal.io/workflow-execution#replay). + +Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that it is compatible with the provided history. + +There are multiple points in your development lifecycle where running replay tests can make sense. They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. + +- During development, replay testing lets you get feedback as early as possible on whether your changes are compatible. For example, you might include some integration tests that run your Workflows against the Temporal Test Server to produce histories which you then check in. You can use those checked-in histories for replay tests to verify you haven't made breaking changes. +- During pre-deployment validation (such as during some automated deployment validation) you can get feedback in a more representative environment. For example, you might fetch histories from a live Temporal environment (whether production or some kind of pre-production) and use them in replay tests. +- At deployment time, your environment _is_ production, but you are using the new code to replay recent real-world Workflow histories. + +When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. You can do the same with the pre-merge CI pipeline. However, if you are using encrypted Payloads, which is a typical and recommended setup in production, you may not be able to decrypt the fetched histories. Additionally if your Workflows contain any PII (which should be encrypted), make sure this information is scrubbed for the purposes of your tests, or err on the side of caution and don't use this method. + +## Implement a deployment-time replay test + +The key to a successful safe deployment is to break it into two phases: a verification phase, where you’ll run the replay test, followed by the actual deployment of your new Worker code. Refer to the [replay testing](https://docs.temporal.io/workflow-execution#replay) docs of each SDK for implementation details. + diff --git a/docs/develop/safe-deployments.mdx b/docs/develop/safe-deployments.mdx deleted file mode 100644 index b4fb5a4174..0000000000 --- a/docs/develop/safe-deployments.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -id: safe-deployments -title: Safely deploying changes to Workflow code -description: Safely deploy changes to existing Workflow code by validating first for determinism errors before deploying to production. -sidebar_label: Safe deployments -toc_max_heading_level: 3 -tags: - - Workflows - - Deployment - - Replay ---- - -Making changes safely to existing Workflow code can be challenging. Your Workflow code must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints). This means your changes to that code have to be as well. Changes to your Workflow code that qualify as non-deterministic need to be protected by either using the [patching APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code, or by [some other versioning strategy.](https://docs.temporal.io/workers#worker-versioning) - -In this article, we’ll provide some advice on how you can safely validate changes to your Workflow code, ensuring that you won’t experience unexpected non-determinism errors in production when rolling them out. - -## Use Replay Testing before and during your deployments - -The best way to verify that your code won’t cause non-determinism errors once deployed is to make use of [replay testing](https://docs.temporal.io/workflow-execution#replay). - -Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that it is compatible with the provided history. - -There are multiple points in your development lifecycle where running replay tests can make sense. They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. - -- During development, replay testing lets you get feedback as early as possible on whether your changes are compatible. For example, you might include some integration tests that run your Workflows against the Temporal Test Server to produce histories which you then check in. You can use those checked-in histories for replay tests to verify you haven’t made breaking changes. -- During pre-deployment validation (such as during some automated deployment validation) you can get feedback in a more representative environment. For example, you might fetch histories from a live Temporal environment (whether production or some kind of pre-production) and use them in replay tests. -- At deployment time, your environment _is_ production, but you are using the new code to replay recent real-world Workflow histories. - -When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. You can do the same with the pre-merge CI pipeline. However, if you are using encrypted Payloads, which is a typical and recommended setup in production, you may not be able to decrypt the fetched histories. Additionally if your Workflows contain any PII (which should be encrypted), make sure this information is scrubbed for the purposes of your tests, or err on the side of caution and don’t use this method. -With that constraint in mind, we’ll focus on how you can perform replay tests in a production deployment of a Worker with new Workflow code. The core of how replay testing is done is the same regardless of when you choose to do it, so you can apply some of the lessons here to earlier stages in your development process. - -## Implement a deployment-time replay test - -The key to a successful safe deployment is to break it into two phases: a verification phase, where you’ll run the replay test, followed by the actual deployment of your new Worker code. - -You can accomplish this by wrapping your Worker application with some code that can choose whether it will run in verification mode, or in production. This is most easily done if you do not deploy your Workers side-by-side with other application code, which is a recommended best practice. If you do deploy your Workers as part of some other application, you will likely need to separate out a different entry point specifically for verification. - -### Run a replay and real Worker with the same code - -The following code demonstrates how the same entry point could be used to either verify the new code using replay testing, or to actually run the Worker. - -```python -import argparse -import asyncio -from datetime import datetime, timedelta - -from temporalio.client import Client -from temporalio.worker import Worker, Replayer - -async def main(): - parser = argparse.ArgumentParser(prog='MyTemporalWorker') - parser.add_argument('mode', choices=['verify', 'run']) - args = parser.parse_args() - - temporal_url = "localhost:7233" - task_queue = "your-task-queue" - my_workflows = [YourWorkflow] - my_activities = [your_activity] - - client = await Client.connect(temporal_url) -``` - -Everything up to this point is standard. You import the Workflow and Activity code, instantiate a parser with two modes, and create your Task Queue, Workflow, and Activity. - -You can pass in the `args.mode` from any appropriate spot in your code. If the mode is set to `verify`, you conduct the replay testing by specifying the time period to test, and passing in the Workflows corresponding to that time period. Note that the Workflows are consumed as histories, using [the `map_histories()` function](https://python.temporal.io/temporalio.client.WorkflowExecutionAsyncIterator.html#map_histories). - -```python -if args.mode == 'verify': - start_time = (datetime.now() - timedelta(hours=10)).isoformat(timespec='seconds') - workflows = client.list_workflows( - f"TaskQueue={task_queue} and StartTime > '{start_time}'", - limit = 100) - histories = workflows.map_histories() - replayer = Replayer( - workflows=my_workflows, - activities=my_activities, - ) - await replayer.replay_workflows(histories) - return -``` - -If any of the Workflows fail to replay, an error will be thrown. If no errors occur, you can return successfully to indicate success here, or communicate with an endpoint you've defined to indicate success or failure of the verification. You could switch to the `run` mode, and have this Worker transition to a real Worker that will start pulling from the Task Queue and processing Workflows: - -```python - else: - worker = Worker( - client, - task_queue=task_queue, - workflows=my_workflows, - activities=my_activities, - ) - await worker.run() - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### Use the multi-modal Worker - -The most straightforward way to use this bimodal Worker is to deploy one instance of it at the beginning of your deployment process in verify mode, see that it passes, and then proceed to deploy the rest of your new workers in run mode. diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index ad9b92b442..ecc8ece1a5 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -12,11 +12,11 @@ tags: :::tip Support, stability, and dependency info -- This version of Worker Versioning is DEPRECATED +- This document refers to the 2023 draft of Worker Versioning, which was deprecated - It was not made available in Temporal Cloud +- The 2024 draft was available in Cloud on an opt-in basis, and is documented in this [Pre-release README.md](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md). -This version of Worker Versioning is deprecated and will go away at some point. -Please see [Worker Versioning](/worker-versioning) instead. +For newer revisions of this feature set, please see [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) instead. ::: diff --git a/docs/encyclopedia/workers/worker-deployments.mdx b/docs/encyclopedia/workers/worker-deployments.mdx deleted file mode 100644 index a82eedc2ad..0000000000 --- a/docs/encyclopedia/workers/worker-deployments.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: worker-deployments -title: What is a Temporal Worker Deployment? -sidebar_label: Worker Deployments -description: Temporal Worker Deployments help you manage and deploy your Worker services. -slug: /worker-deployments -toc_max_heading_level: 4 -keywords: - - workers - - versioning - - deployments - - deployment versions -tags: - - Workers - - Concepts - - Deployments - - Deployment Versions ---- - -This page defines [Worker Deployments](#deployments) and [Worker Deployment Versions](#deployment-versions) and explains their use cases. - -:::tip SUPPORT, STABILITY, and DEPENDENCY INFO - -The Worker Deployments feature is available in [Pre-release](/evaluate/development-production-features/release-stages#pre-release). - -Supported Worker Deployment Clients include: - -- Temporal CLI: version [v1.3.0](https://github.com/temporalio/cli/releases/tag/v1.3.0) or higher -- Go SDK: version [v1.33.0](https://github.com/temporalio/sdk-go/releases/tag/v1.33.0) or higher -- Other SDKs: coming soon! - -Open source users need: - -- Temporal Server: version [v1.27.1](https://github.com/temporalio/temporal/releases/tag/v1.27.1) or higher -- Open Source UI: version [v2.36.0](https://github.com/temporalio/ui/releases/tag/v2.36.0) or higher - -::: - -## What are Worker Deployments? {#deployments} - -A Worker Deployment is a logical service that groups similar Workers together for unified management. -Each Deployment has a name (such as your service name) and supports versioning through a series of [Worker Deployment Versions](#deployment-versions). - -## What are Worker Deployment Versions? {#deployment-versions} - -A Worker Deployment Version represents an iteration of a Worker Deployment. -Each Deployment Version consists of Workers that share the same code build and environment. -When a Worker starts polling for Workflow and Activity Tasks, it reports its Deployment Version to the Temporal Server. - -## What can I do with Worker Deployments? {#use-cases} - -Worker Deployments currently support [Worker Versioning](/worker-versioning), with more features planned for the future. - -## How do I enable Worker Deployments? {#how-to} - -:::note - -Temporal Server disables Worker Deployments by default. - -Temporal Cloud customers: Contact your Temporal account team or the [Temporal Support Team](https://docs.temporal.io/cloud/support#support-ticket) for Pre-release access. - -Open source users: Enable the [system.enableDeploymentVersions](https://github.com/temporalio/temporal/blob/main/common/dynamicconfig/constants.go) and [frontend.workerVersioningWorkflowAPIs](https://github.com/temporalio/temporal/blob/main/common/dynamicconfig/constants.go) dynamic config values by setting both to `true`. - -For example, with the Temporal CLI, run: - -```command -temporal server start-dev \ - --dynamic-config-value system.enableDeploymentVersions=true \ - --dynamic-config-value frontend.workerVersioningWorkflowAPIs=true -``` - -::: - -To add your Worker to a Deployment, provide both the Deployment name and Version when creating your Worker. -When your deployment system is ready, turn on Versioning as well. Refer to [Worker Versioning](/worker-versioning) for details. - -When running multiple Workers in one process (such as using multiple [Task Queues](/task-queue)), you'll typically use the same Deployment name for all of them, since they belong to the same service. - -The server will automatically register new Deployments and Deployment Versions when a Worker connects. You can see the status of Versions on the Deployments page in [Temporal UI](https://docs.temporal.io/web-ui). - -:::info - -SDK-specific documentation will be available soon. - -::: diff --git a/docs/encyclopedia/workers/worker-versioning.mdx b/docs/encyclopedia/workers/worker-versioning.mdx deleted file mode 100644 index 404adb055d..0000000000 --- a/docs/encyclopedia/workers/worker-versioning.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: worker-versioning -title: Worker Versioning -sidebar_label: Worker Versioning -description: Understand how Worker Versioning facilitates deployment changes. -slug: /worker-versioning -toc_max_heading_level: 4 -keywords: - - safe deployments - - worker versioning - - deployments - - deployment versions -tags: - - Workers - - Concepts - - Worker Versioning ---- - -This page discusses [Worker Versioning](#worker-versioning). - -## What is Worker Versioning? {#worker-versioning} - -Worker Versioning documentation is coming soon! - -For now, please join #safe-deploys in our [Community Slack](https://temporal.io/slack) to find the latest status and pre-release docs. - -If you're using the deprecated version that shipped in mid-2024, see the [Pre-release README.md](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md). - -If you're using the deprecated version that was released in late 2023, go [here](/encyclopedia/worker-versioning-legacy.mdx). diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index a5d505584d..352f5df3f0 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -238,23 +238,16 @@ In other words, all operations that do not purely mutate the Workflow Execution' The Temporal Platform requires that Workflow code (Workflow Definitions) be deterministic in nature. This requirement means that developers should consider how they plan to handle changes to Workflow code over time. -A versioning strategy is even more important if your Workflow Executions live long enough that a Worker must be able to execute multiple versions of the same Workflow Type. +A versioning strategy is even more important if your Workflow Executions live long enough that a Worker must be able to execute multiple versions of the same Workflow Type. Temporal Platform provides Workflow Versioning APIs. -Apart from the ability to create new Task Queues for Workflow Types with the same name, the Temporal Platform provides Workflow Patching APIs and Worker Build Id–based versioning features. +- [How to version Workflow code in Go](/develop/go/versioning) +- [How to version Workflow code in Java](/develop/java/versioning) +- [How to version Workflow code in Python](/develop/python/versioning) +- [How to version Workflow code in PHP](/develop/php/versioning) +- [How to version Workflow code in TypeScript](/develop/typescript/versioning) +- [How to version Workflow code in .NET](/develop/dotnet/versioning) -#### Patching - -Patching APIs enable the creation of logical branching inside a Workflow Definition based on a developer-specified version identifier. -This feature is useful for Workflow Definition logic that needs to be updated but still has running Workflow Executions that depend on it. - -- [How to patch Workflow code in Go](/develop/go/versioning#patching) -- [How to patch Workflow code in Java](/develop/java/versioning#patching) -- [How to patch Workflow code in Python](/develop/python/versioning#python-sdk-patching-api) -- [How to patch Workflow code in PHP](/develop/php/versioning#php-sdk-patching-api) -- [How to patch Workflow code in TypeScript](/develop/typescript/versioning#patching) -- [How to patch Workflow code in .NET](/develop/dotnet/versioning#dotnet-sdk-patching-api) - -You can also use [Worker Versioning](/worker-versioning) instead of Patching. +Temporal also has a [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature that allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](/encyclopedia/worker-versioning-legacy). ### Handling unreliable Worker Processes {#unreliable-worker-processes} diff --git a/docs/production-deployment/index.mdx b/docs/production-deployment/index.mdx index 89e3e9bb11..8f38f7264b 100644 --- a/docs/production-deployment/index.mdx +++ b/docs/production-deployment/index.mdx @@ -41,3 +41,8 @@ Follow the [Self-hosted guide](/self-hosted-guide) to get started. src="/diagrams/basic-platform-topology-self-hosted.svg" title="Connect your application instances to your self-hosted Temporal Service" /> + +## Worker deployments + +Whether you're hosting with Temporal Cloud or on your own, you have control over where to run and scale your Workers. +[This section](/worker-deployments) provides guidance on Worker deployments. \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index dfe34951d4..3d1e8e4cac 100644 --- a/sidebars.js +++ b/sidebars.js @@ -271,7 +271,7 @@ module.exports = { }, "develop/activity-retry-simulator", "develop/worker-performance", - "develop/safe-deployments", + "develop/determinism", ], }, { @@ -478,6 +478,19 @@ module.exports = { "production-deployment/self-hosted-guide/server-frontend-api-reference", ], }, + { + type: "category", + label: "Worker deployments", + collapsed: true, + link: { + type: "doc", + id: "production-deployment/worker-deployments/index", + }, + items: [ + "production-deployment/worker-deployments/safe-deploys", + "production-deployment/worker-deployments/kubernetes-controller", + ], + }, ], }, { @@ -623,8 +636,6 @@ module.exports = { "encyclopedia/workers/task-queue-naming", "encyclopedia/workers/task-routing-worker-sessions", "encyclopedia/workers/sticky-execution", - "encyclopedia/workers/worker-deployments", - "encyclopedia/workers/worker-versioning", ], }, { diff --git a/vercel.json b/vercel.json index dc542188b0..d7e996455e 100644 --- a/vercel.json +++ b/vercel.json @@ -1954,6 +1954,21 @@ "source": "/production-deployment/cloud/metrics/performance-bottlenecks", "destination": "/troubleshooting/performance-bottlenecks", "permanent": true + }, + { + "source": "/worker-deployments", + "destination": "/production-deployment/worker-deployments", + "permanent": true + }, + { + "source": "/worker-versioning", + "destination": "/production-deployment/worker-deployments/safe-deploys", + "permanent": true + }, + { + "source": "/develop/safe-deployments", + "destination": "/develop/determinism", + "permanent": true } ] } From 8a9e4c2a22c4c16803ef701d98f41d0bb7451fd1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Jun 2025 17:06:40 +0000 Subject: [PATCH 10/78] CI: Automatic .md and .mdx formatting --- docs/develop/determinism.mdx | 1 - docs/production-deployment/index.mdx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx index 45bf35bf43..1cc9c1cc38 100644 --- a/docs/develop/determinism.mdx +++ b/docs/develop/determinism.mdx @@ -29,4 +29,3 @@ When you're writing changes to Workflow code, you can fetch some representative ## Implement a deployment-time replay test The key to a successful safe deployment is to break it into two phases: a verification phase, where you’ll run the replay test, followed by the actual deployment of your new Worker code. Refer to the [replay testing](https://docs.temporal.io/workflow-execution#replay) docs of each SDK for implementation details. - diff --git a/docs/production-deployment/index.mdx b/docs/production-deployment/index.mdx index 8f38f7264b..eb25a94844 100644 --- a/docs/production-deployment/index.mdx +++ b/docs/production-deployment/index.mdx @@ -45,4 +45,4 @@ Follow the [Self-hosted guide](/self-hosted-guide) to get started. ## Worker deployments Whether you're hosting with Temporal Cloud or on your own, you have control over where to run and scale your Workers. -[This section](/worker-deployments) provides guidance on Worker deployments. \ No newline at end of file +[This section](/worker-deployments) provides guidance on Worker deployments. From 55884088d0945b5daeee714120e5654fdcbb081f Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 11:04:54 -0700 Subject: [PATCH 11/78] add new worker deployments pages --- .../worker-deployments/index.mdx | 22 ++++++ .../kubernetes-controller.mdx | 67 +++++++++++++++++++ .../worker-deployments/safe-deploys.mdx | 18 +++++ 3 files changed, 107 insertions(+) create mode 100644 docs/production-deployment/worker-deployments/index.mdx create mode 100644 docs/production-deployment/worker-deployments/kubernetes-controller.mdx create mode 100644 docs/production-deployment/worker-deployments/safe-deploys.mdx diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx new file mode 100644 index 0000000000..c7e2aedfcd --- /dev/null +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -0,0 +1,22 @@ +--- +id: index +title: Temporal Worker Deployments +sidebar_label: Worker Deployments +description: Learn how to programmatically scale and deploy your Temporal Workers into common production environments using our provided tooling and best practices. +slug: /production-deployments/worker-deployments +toc_max_heading_level: 4 +keywords: + - kubernetes + - scaling + - workers + - deploys + - versioning +tags: + - Temporal Service + - Durable Execution +--- + +TK TK TK + +- [Safe Deploys](/production-deployments/worker-deployments/safe-deploys) +- [Temporal Worker Controller](/production-deployments/worker-deployments/kubernetes-controller) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx new file mode 100644 index 0000000000..c36d352037 --- /dev/null +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -0,0 +1,67 @@ +--- +id: kubernetes-controller +title: Temporal Worker Controller +sidebar_label: Kubernetes controller +description: Use Temporal's provided Kubernetes controller to programmatically scale your Worker deployments. +slug: /production-deployments/worker-deployments/kubernetes-controller +toc_max_heading_level: 4 +keywords: + - kubernetes + - scaling + - helm + - workers + - scaling + - versioning +tags: + - Temporal Service + - Durable Execution +--- + +Temporal's [deterministic constraints](/workflows#deterministic-constraints) can cause challenges when rolling out or rolling back workflow code changes. + +The traditional approach to workflow determinism is to add branches using the [Versioning APIs](/workflow-definition#workflow-versioning). +Over time these checks can become a source of technical debt, as safely removing them from a codebase is a careful process that often involves querying all running workflows. + +[Safe Deploys](/production-deployments/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +Using pinning, you will not need to patch most Workflows as part of routine deploys. +If Activities and Workflows are running in the same worker deployment version, you also do not need to ensure interface compatibility across versions. + +This greatly simplifies Workflow upgrades, but the cost is that your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. +This is typically known as a rainbow deploy (of which a blue-green deploy is a special case) and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. + +This project aims to provide automation to enable rainbow deployments of your workers by simplifying the tracking of which versions still have active workflows, managing the lifecycle of versioned worker deployments, and calling Temporal APIs to update the routing config of Temporal Worker Deployments. +This way, you can route Workflow traffic to new versions. + +Note that in Temporal, **Worker Deployment** is sometimes referred to as **Deployment**, but since the controller makes significant references to Kubernetes Deployment resource, within this page we will stick to these terms: + +- **Worker Deployment Version**: A version of a deployment or service. It can have multiple Workers, but they all run the same build. Sometimes shortened to "version" or "deployment version." +- **Worker Deployment**: A deployment or service across multiple versions. In a rainbow deploy, a worker deployment can have multiple active deployment versions running at once. +- **Deployment**: A Kubernetes Deployment resource. A Deployment is "versioned" if it is running versioned Temporal workers/pollers. + +## Running the Temporal Worker Controller + +Refer to [Github](https://github.com/DataDog/temporal-worker-controller/blob/main/internal/README.md) for instructions on how to run the Temporal Worker Controller with Minikube. + +More usage details are coming soon. + +## Configuring Worker Lifecycle + +To use the Temporal Worker Controller, tag your Workers following the guidance for using [Safe Deploys](/production-deployments/worker-deployments/safe-deploys). This means specifying a `TEMPORAL_DEPLOYMENT_NAME` and a `WORKER_BUILD_ID` in addition to the stock hostname and namespace configuration parameters. + +When a new worker deployment version is deployed, the worker controller detects it and automatically begins the process of making that version the new current (default) version of the worker deployment it is a part of. This could happen immediately if `cutover.strategy = AllAtOnce`, or gradually if `cutover.strategy = Progressive`. + +As older pinned workflows finish executing and deprecated deployment versions become drained, the worker controller also frees up resources by sunsetting the `Deployment` resources polling those versions. + +Here is an example of a progressive cut-over strategy gated on the success of the `HelloWorld` workflow: + +``` +cutover: + strategy: Progressive + steps: + - rampPercentage: 1 + pauseDuration: 30s + - rampPercentage: 10 + pauseDuration: 1m + gate: + workflowType: "HelloWorld" +``` \ No newline at end of file diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx new file mode 100644 index 0000000000..1f923a7d01 --- /dev/null +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -0,0 +1,18 @@ +--- +id: safe-deploys +title: Safe Deploys +sidebar_label: Safe Deploys +description: Use Safe Deploys to pin Workflow revisions to individual Worker Deployment Versions, avoiding the need for branching to support multiple code paths. +slug: /production-deployments/worker-deployments/safe-deploys +toc_max_heading_level: 4 +keywords: + - scaling + - workers + - versioning + - deploys +tags: + - Temporal Service + - Durable Execution +--- + +TK TK TK \ No newline at end of file From ae9f083c15ab8a7566a6122afcb1c2f9e56e1613 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Jun 2025 18:05:56 +0000 Subject: [PATCH 12/78] CI: Automatic .md and .mdx formatting --- .../worker-deployments/kubernetes-controller.mdx | 2 +- docs/production-deployment/worker-deployments/safe-deploys.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index c36d352037..e7488cdd6f 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -64,4 +64,4 @@ cutover: pauseDuration: 1m gate: workflowType: "HelloWorld" -``` \ No newline at end of file +``` diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 1f923a7d01..4b2b0f3b23 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -15,4 +15,4 @@ tags: - Durable Execution --- -TK TK TK \ No newline at end of file +TK TK TK From 5155062535a6bea77df2225083a1644ffe537832 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 11:12:40 -0700 Subject: [PATCH 13/78] fix broken links --- docs/develop/dotnet/versioning.mdx | 2 +- docs/develop/go/worker-versioning-legacy.mdx | 2 +- docs/develop/java/worker-versioning-legacy.mdx | 2 +- docs/develop/python/worker-versioning-legacy.mdx | 2 +- docs/develop/typescript/worker-versioning-legacy.mdx | 2 +- docs/encyclopedia/worker-versioning-legacy.mdx | 2 +- docs/production-deployment/index.mdx | 2 +- docs/production-deployment/worker-deployments/index.mdx | 6 +++--- .../worker-deployments/kubernetes-controller.mdx | 6 +++--- .../worker-deployments/safe-deploys.mdx | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index 5f759039d9..67779406bb 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -37,7 +37,7 @@ There are three primary Versioning methods supported by Temporal: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. - [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. ## Workflow Type Versioning {#type-versioning} diff --git a/docs/develop/go/worker-versioning-legacy.mdx b/docs/develop/go/worker-versioning-legacy.mdx index e5787a87b9..e7d1b0644a 100644 --- a/docs/develop/go/worker-versioning-legacy.mdx +++ b/docs/develop/go/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. diff --git a/docs/develop/java/worker-versioning-legacy.mdx b/docs/develop/java/worker-versioning-legacy.mdx index da216c89e9..11ad15ea99 100644 --- a/docs/develop/java/worker-versioning-legacy.mdx +++ b/docs/develop/java/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. diff --git a/docs/develop/python/worker-versioning-legacy.mdx b/docs/develop/python/worker-versioning-legacy.mdx index 0aeba0111b..69a52b0674 100644 --- a/docs/develop/python/worker-versioning-legacy.mdx +++ b/docs/develop/python/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. diff --git a/docs/develop/typescript/worker-versioning-legacy.mdx b/docs/develop/typescript/worker-versioning-legacy.mdx index 317f507c6e..52f6e7ab1b 100644 --- a/docs/develop/typescript/worker-versioning-legacy.mdx +++ b/docs/develop/typescript/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index ecc8ece1a5..7c0fb0087a 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -34,7 +34,7 @@ Accomplish this goal by assigning a Build ID (a free-form string) to the code th :::caution -This version of Worker Versioning is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning) +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: diff --git a/docs/production-deployment/index.mdx b/docs/production-deployment/index.mdx index eb25a94844..de58ccd5f5 100644 --- a/docs/production-deployment/index.mdx +++ b/docs/production-deployment/index.mdx @@ -45,4 +45,4 @@ Follow the [Self-hosted guide](/self-hosted-guide) to get started. ## Worker deployments Whether you're hosting with Temporal Cloud or on your own, you have control over where to run and scale your Workers. -[This section](/worker-deployments) provides guidance on Worker deployments. +We provide guidance on [Worker Deployments](/production-deployment/worker-deployments). diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx index c7e2aedfcd..c2f6d45ae9 100644 --- a/docs/production-deployment/worker-deployments/index.mdx +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -3,7 +3,7 @@ id: index title: Temporal Worker Deployments sidebar_label: Worker Deployments description: Learn how to programmatically scale and deploy your Temporal Workers into common production environments using our provided tooling and best practices. -slug: /production-deployments/worker-deployments +slug: /production-deployment/worker-deployments toc_max_heading_level: 4 keywords: - kubernetes @@ -18,5 +18,5 @@ tags: TK TK TK -- [Safe Deploys](/production-deployments/worker-deployments/safe-deploys) -- [Temporal Worker Controller](/production-deployments/worker-deployments/kubernetes-controller) +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) +- [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index c36d352037..ec728e087e 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -3,7 +3,7 @@ id: kubernetes-controller title: Temporal Worker Controller sidebar_label: Kubernetes controller description: Use Temporal's provided Kubernetes controller to programmatically scale your Worker deployments. -slug: /production-deployments/worker-deployments/kubernetes-controller +slug: /production-deployment/worker-deployments/kubernetes-controller toc_max_heading_level: 4 keywords: - kubernetes @@ -22,7 +22,7 @@ Temporal's [deterministic constraints](/workflows#deterministic-constraints) can The traditional approach to workflow determinism is to add branches using the [Versioning APIs](/workflow-definition#workflow-versioning). Over time these checks can become a source of technical debt, as safely removing them from a codebase is a careful process that often involves querying all running workflows. -[Safe Deploys](/production-deployments/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +[Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. Using pinning, you will not need to patch most Workflows as part of routine deploys. If Activities and Workflows are running in the same worker deployment version, you also do not need to ensure interface compatibility across versions. @@ -46,7 +46,7 @@ More usage details are coming soon. ## Configuring Worker Lifecycle -To use the Temporal Worker Controller, tag your Workers following the guidance for using [Safe Deploys](/production-deployments/worker-deployments/safe-deploys). This means specifying a `TEMPORAL_DEPLOYMENT_NAME` and a `WORKER_BUILD_ID` in addition to the stock hostname and namespace configuration parameters. +To use the Temporal Worker Controller, tag your Workers following the guidance for using [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). This means specifying a `TEMPORAL_DEPLOYMENT_NAME` and a `WORKER_BUILD_ID` in addition to the stock hostname and namespace configuration parameters. When a new worker deployment version is deployed, the worker controller detects it and automatically begins the process of making that version the new current (default) version of the worker deployment it is a part of. This could happen immediately if `cutover.strategy = AllAtOnce`, or gradually if `cutover.strategy = Progressive`. diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 1f923a7d01..c848865cc4 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -3,7 +3,7 @@ id: safe-deploys title: Safe Deploys sidebar_label: Safe Deploys description: Use Safe Deploys to pin Workflow revisions to individual Worker Deployment Versions, avoiding the need for branching to support multiple code paths. -slug: /production-deployments/worker-deployments/safe-deploys +slug: /production-deployment/worker-deployments/safe-deploys toc_max_heading_level: 4 keywords: - scaling From 15ea33e7d46d60c1bbba33e5ce6318542e17645e Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 11:22:45 -0700 Subject: [PATCH 14/78] a few more broken links --- docs/develop/go/worker-versioning-legacy.mdx | 6 ++---- docs/develop/java/worker-versioning-legacy.mdx | 4 ++-- docs/develop/python/worker-versioning-legacy.mdx | 6 +++--- docs/develop/typescript/worker-versioning-legacy.mdx | 8 +++----- docs/encyclopedia/worker-versioning-legacy.mdx | 4 ++-- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/docs/develop/go/worker-versioning-legacy.mdx b/docs/develop/go/worker-versioning-legacy.mdx index e7d1b0644a..44386da853 100644 --- a/docs/develop/go/worker-versioning-legacy.mdx +++ b/docs/develop/go/worker-versioning-legacy.mdx @@ -23,7 +23,7 @@ See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/do ::: A Build ID corresponds to a deployment. If you don't already have one, we recommend a hash of the code--such as a Git SHA--combined with a human-readable timestamp. -To use [Worker Versioning](/worker-versioning), you need to pass a Build ID to your Go Worker and opt in to Worker Versioning. +To use Worker Versioning, you need to pass a Build ID to your Go Worker and opt in to Worker Versioning. ### Assign a Build ID to your Worker and opt in to Worker Versioning @@ -56,8 +56,6 @@ When configured to run on a separate Task Queue, they will default to using the If you want to override this behavior, you can specify your intent via the `VersioningIntent` field on the appropriate options struct. -{/* For more information refer to the [conceptual documentation](/worker-versioning). */} - For example, if you want an Activity to use the latest assignment rules rather than inheriting from its parent: ```go @@ -85,7 +83,7 @@ err := workflow.NewContinueAsNewError(ctx, "WorkflowName") :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: diff --git a/docs/develop/java/worker-versioning-legacy.mdx b/docs/develop/java/worker-versioning-legacy.mdx index 11ad15ea99..528eb2cb34 100644 --- a/docs/develop/java/worker-versioning-legacy.mdx +++ b/docs/develop/java/worker-versioning-legacy.mdx @@ -22,7 +22,7 @@ See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/do ::: A Build ID corresponds to a deployment. If you don't already have one, we recommend a hash of the code--such as a Git SHA--combined with a human-readable timestamp. -To use [Worker Versioning](/worker-versioning), you need to pass a Build ID to your Java Worker and opt in to Worker Versioning. +To use Worker Versioning, you need to pass a Build ID to your Java Worker and opt in to Worker Versioning. ### Assign a Build ID to your Worker and opt in to Worker Versioning @@ -81,7 +81,7 @@ private final MyActivity activity = :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: diff --git a/docs/develop/python/worker-versioning-legacy.mdx b/docs/develop/python/worker-versioning-legacy.mdx index 69a52b0674..0df8660e09 100644 --- a/docs/develop/python/worker-versioning-legacy.mdx +++ b/docs/develop/python/worker-versioning-legacy.mdx @@ -23,7 +23,7 @@ See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/do ::: A Build ID corresponds to a deployment. If you don't already have one, we recommend a hash of the code--such as a Git SHA--combined with a human-readable timestamp. -To use [Worker Versioning](/worker-versioning), you need to pass a Build ID to your Java Worker and opt in to Worker Versioning. +To use Worker Versioning, you need to pass a Build ID to your Java Worker and opt in to Worker Versioning. ### Assign a Build ID to your Worker and opt in to Worker Versioning @@ -53,7 +53,7 @@ Importantly, when you start this Worker, it won't receive any tasks until you se :::caution -Python support for this feature is under construction! +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: @@ -79,7 +79,7 @@ await workflow.execute_activity( :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: diff --git a/docs/develop/typescript/worker-versioning-legacy.mdx b/docs/develop/typescript/worker-versioning-legacy.mdx index 52f6e7ab1b..557835a5ee 100644 --- a/docs/develop/typescript/worker-versioning-legacy.mdx +++ b/docs/develop/typescript/worker-versioning-legacy.mdx @@ -23,7 +23,7 @@ See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/do ::: A Build ID corresponds to a deployment. If you don't already have one, we recommend a hash of the code--such as a Git SHA--combined with a human-readable timestamp. -To use [Worker Versioning](/worker-versioning), you need to pass a Build ID to your Typescript Worker and opt in to Worker Versioning. +To use Worker Versioning, you need to pass a Build ID to your Typescript Worker and opt in to Worker Versioning. ### Assign a Build ID to your Worker and opt in to Worker Versioning @@ -53,7 +53,7 @@ Importantly, when you start this Worker, it won't receive any tasks until you se :::caution -Typescript support for this feature is under construction! +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: @@ -63,8 +63,6 @@ When configured to run on a separate task queue, they will default to using the If you want to override this behavior, you can specify your intent via the `versioningIntent` field available on the options object for each of these commands. -{/* For more information refer to the [conceptual documentation](/worker-versioning). */} - For example, if you want an Activity to use the latest assignment rules rather than inheriting from its parent: ```typescript @@ -80,7 +78,7 @@ const { echo } = proxyActivities({ :::caution -This section is for a previous Worker Versioning API that is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index 7c0fb0087a..884c24c3a0 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -95,7 +95,7 @@ You also have the option to specify that the continued Workflow should start usi :::caution -This version of Worker Versioning is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning) +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: @@ -220,7 +220,7 @@ This limit is configurable on the server via the `limit.workerBuildIdSize` dynam :::caution -This version of Worker Versioning is deprecated and will go away at some point. Please redirect your attention to [Worker Versioning](/worker-versioning) +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: From d0eec664616cfae5eab1bb0eed0e0311da20b575 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 11:30:09 -0700 Subject: [PATCH 15/78] surgery is fun --- docs/develop/dotnet/index.mdx | 2 +- docs/develop/go/index.mdx | 3 +-- docs/develop/java/index.mdx | 3 +-- docs/develop/python/index.mdx | 5 ++--- docs/develop/typescript/index.mdx | 3 +-- .../worker-deployments/kubernetes-controller.mdx | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/docs/develop/dotnet/index.mdx b/docs/develop/dotnet/index.mdx index 8731245af7..e2d457a96e 100644 --- a/docs/develop/dotnet/index.mdx +++ b/docs/develop/dotnet/index.mdx @@ -115,7 +115,7 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. -- [Use the .NET SDK Patching API](/develop/dotnet/versioning#dotnet-sdk-patching-api): Patching Workflows using the .NET SDK. +- [Use the .NET SDK Patching API](/develop/dotnet/versioning#patching): Patching Workflows using the .NET SDK. ## [Observability](/develop/dotnet/observability) diff --git a/docs/develop/go/index.mdx b/docs/develop/go/index.mdx index 15fbfa295b..e4b2d1ad07 100644 --- a/docs/develop/go/index.mdx +++ b/docs/develop/go/index.mdx @@ -98,9 +98,8 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. -- [Temporal Go SDK Patching APIs](/develop/go/versioning#patching) +- [Temporal Go SDK Versioning APIs](/develop/go/versioning#getversion) - [Sanity checking](/develop/go/versioning#sanity-checking) -- [How to use Worker Versioning in Go](/develop/go/versioning#worker-versioning) ## [Observability](/develop/go/observability) diff --git a/docs/develop/java/index.mdx b/docs/develop/java/index.mdx index 21f85f88f1..99d6282224 100644 --- a/docs/develop/java/index.mdx +++ b/docs/develop/java/index.mdx @@ -85,8 +85,7 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. -- [How to patch Workflows in Java](/develop/java/versioning#patching) -- [How to use Worker Versioning in Java](/develop/java/versioning#worker-versioning) +- [Temporal Java SDK Versioning APIs](/develop/java/versioning#getversion) ## [Observability](/develop/java/observability) diff --git a/docs/develop/python/index.mdx b/docs/develop/python/index.mdx index 333f9b5677..7ded959b2b 100644 --- a/docs/develop/python/index.mdx +++ b/docs/develop/python/index.mdx @@ -101,9 +101,8 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. -- [Introduction to Versioning](/develop/python/versioning#introduction-to-versioning) -- [How to Use the Patching API](/develop/python/versioning#python-sdk-patching-api) -- [How to Use Worker Versioning](/develop/python/versioning#worker-versioning) +- [Introduction to Versioning](/develop/python/versioning) +- [How to Use the Patching API](/develop/python/versioning#patching) ## [Observability](/develop/python/observability) diff --git a/docs/develop/typescript/index.mdx b/docs/develop/typescript/index.mdx index ecc34cba31..8586edc96a 100644 --- a/docs/develop/typescript/index.mdx +++ b/docs/develop/typescript/index.mdx @@ -90,8 +90,7 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. - [Introduction to Versioning](/develop/typescript/versioning) -- [How to Use the Patching API](/develop/typescript/versioning#typescript-sdk-patching-api) -- [How to Use Worker Versioning](/develop/typescript/versioning#worker-versioning) +- [How to Use the Patching API](/develop/typescript/versioning#patching) ## [Observability](/develop/typescript/observability) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index 53866a99dd..a2598175cf 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -17,7 +17,7 @@ tags: - Durable Execution --- -Temporal's [deterministic constraints](/workflows#deterministic-constraints) can cause challenges when rolling out or rolling back workflow code changes. +Temporal's [deterministic constraints](/workflow-definition#deterministic-constraints) can cause challenges when rolling out or rolling back workflow code changes. The traditional approach to workflow determinism is to add branches using the [Versioning APIs](/workflow-definition#workflow-versioning). Over time these checks can become a source of technical debt, as safely removing them from a codebase is a careful process that often involves querying all running workflows. From 3bd5312731ea6324283ecb6a5da58f7a092d9336 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 12:10:20 -0700 Subject: [PATCH 16/78] add top level worker deployments page --- .../worker-deployments/index.mdx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx index c2f6d45ae9..4d474626e0 100644 --- a/docs/production-deployment/worker-deployments/index.mdx +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -16,7 +16,16 @@ tags: - Durable Execution --- -TK TK TK +A core feature of Temporal is that you are able to deploy your Workers to any infrastructure where your Workflow and Activity code will actually run. +This way, you have total control over your runtime environment, and can be responsive to any security or scaling needs that may arise over time, whether you are using Temporal Cloud or self-hosting a Temporal Service. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) -- [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) +However, if you do not already have some expertise in site reliability engineering, or do not know how to migrate from a Docker deployment to (for example) a Kubernetes pod of Temporal Workers, you may want more direct guidance here. +For example, most of our [Tutorials and Courses](https://learn.temporal.io/) use only one or two Temporal Workers to demonstrate core functionality. +The content in this section will provide clarity on real-world deployments that grow far beyond those examples. + +Our Worker Deployments guide provides documentation of Temporal product features that make it easier to scale and revise your Workflows. +One of these features, [Safe Deploys](/production-deployment/worker-deployments/safe-deploys), allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +Using pinning, you will not need to patch most Workflows as part of routine deploys. +We also provide a [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) for using these features with a sample Kubernetes deployment. + +You can also refer to our [Code Exchange](https://temporal.io/code-exchange) for community-contributed deployments. \ No newline at end of file From 16f75c1f62e926ca579effb5f7ceba1829bb1782 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 4 Jun 2025 19:11:09 +0000 Subject: [PATCH 17/78] CI: Automatic .md and .mdx formatting --- docs/production-deployment/worker-deployments/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx index 4d474626e0..807be9b32e 100644 --- a/docs/production-deployment/worker-deployments/index.mdx +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -28,4 +28,4 @@ One of these features, [Safe Deploys](/production-deployment/worker-deployments/ Using pinning, you will not need to patch most Workflows as part of routine deploys. We also provide a [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) for using these features with a sample Kubernetes deployment. -You can also refer to our [Code Exchange](https://temporal.io/code-exchange) for community-contributed deployments. \ No newline at end of file +You can also refer to our [Code Exchange](https://temporal.io/code-exchange) for community-contributed deployments. From 98a9e414a2582de038128ca8058963a253db70cb Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 12:33:40 -0700 Subject: [PATCH 18/78] add bullets for worker deployments index page --- docs/production-deployment/worker-deployments/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx index 4d474626e0..df21b9e975 100644 --- a/docs/production-deployment/worker-deployments/index.mdx +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -24,8 +24,8 @@ For example, most of our [Tutorials and Courses](https://learn.temporal.io/) use The content in this section will provide clarity on real-world deployments that grow far beyond those examples. Our Worker Deployments guide provides documentation of Temporal product features that make it easier to scale and revise your Workflows. -One of these features, [Safe Deploys](/production-deployment/worker-deployments/safe-deploys), allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. -Using pinning, you will not need to patch most Workflows as part of routine deploys. -We also provide a [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) for using these features with a sample Kubernetes deployment. + +- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +- The [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) helps configure these features for a sample Kubernetes deployment. You can also refer to our [Code Exchange](https://temporal.io/code-exchange) for community-contributed deployments. \ No newline at end of file From c905bc07206a24b760b104a279a24d72211df9dc Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 15:26:56 -0700 Subject: [PATCH 19/78] add safe deploys page and sdktabs component --- .../worker-deployments/safe-deploys.mdx | 391 ++++++++++++++++++ package.json | 1 + src/components/elements/SdkTabs/Languages.ts | 20 + src/components/elements/SdkTabs/index.js | 75 ++++ src/components/index.js | 6 +- src/constants/languageTabs.js | 18 + src/constants/sdkLanguages.js | 14 + 7 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 src/components/elements/SdkTabs/Languages.ts create mode 100644 src/components/elements/SdkTabs/index.js create mode 100644 src/constants/languageTabs.js create mode 100644 src/constants/sdkLanguages.js diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 947f2b05e3..a4a6858c75 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -15,4 +15,395 @@ tags: - Durable Execution --- +import { LANGUAGE_TAB_GROUP, getLanguageLabel } from '@site/src/constants/languageTabs'; +import SdkTabs from '@site/src/components'; + +[Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +Using pinning, you will not need to patch most Workflows as part of routine deploys. +If Activities and Workflows are running in the same worker deployment version, you also do not need to ensure interface compatibility across versions. + +This allows you to bypass the other Versioning APIs. +Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. +This is typically known as a rainbow deploy (of which a blue-green deploy is a special case) and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. + +:::tip +Watch this Temporal Replay 2025 talk to learn more about Safe Deploys. + +
+ +
+::: + +:::note +Safe Deploys is currently available in Pre-release. + +Minimum versions: +- Go SDK version v1.33.0 +- Python v1.11 +- Java v1.29 +- Typescript v1.12 +- Other SDKs: coming soon! + +Self-hosted users: + +Minimum Temporal CLI version v1.3.0 +Minimum Temporal Server version: v1.27.1 +Minimum Temporal UI Version v2.36.0 +::: + +## Getting Started with Safe Deploys + +First, we'll introduce some terminology. + +- A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. +- A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. +- A **Build ID**, in combination with a Worker Deployment name, identifies a single Worker Deployment Version. + - Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to drain pinned workflows or in case you need to roll back. If no current version is specified, the default is unversioned. + - Each Worker Deployment can have a **Ramping Version** which is where a configurable percentage of workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no ramping version is specified, 100% of auto-upgrade workflows will go to the Current Version. + - You can declare each Workflow type to have a **Versioning Behavior**, either `pinned` or `auto-upgraded`. A `pinned` Worfklow is guaranteed to complete on a single Worker Deployment Version. An `auto-upgraded` Workflow will move to the latest Worker Deployment Version automatically whenever you change the current version. + +Your deployment system should support rainbow deployments so that you can keep versions alive to drain existing workflows. +The [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) provides an example of using Kubernetes to bootstrap a rainbow deployment. + +### Opting into the Pre-release + TK TK TK + +``` +temporal server start-dev \ + --dynamic-config-value frontend.workerVersioningWorkflowAPIs=true \ + --dynamic-config-value system.enableDeploymentVersions=true +``` + +## Configuring a Worker for Safe Deploys + +You'll need to TK TK TK + + + +```go +buildID:= mustGetEnv("MY_BUILD_ID") +w := worker.New(c, myTaskQueue, worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + // Must be in this exact format: . + Version: "llm_srv." + buildID, + DefaultVersioningBehavior: workflow.VersioningBehaviorAutoUpgrade, +}, +}) +``` + + +```java +WorkerOptions options = + WorkerOptions.newBuilder() + .setDeploymentOptions( + WorkerDeploymentOptions.newBuilder() + .setVersion(new WorkerDeploymentVersion("llm_srv", "1.0")) + .setUseVersioning(true) + .setDefaultVersioningBehavior(VersioningBehavior.AUTO_UPGRADE) + .build()) + .build(); +``` + + +```python +Worker( + client, + task_queue="mytaskqueue", + workflows=workflows, + activities=activities, + deployment_config=WorkerDeploymentConfig( + version=WorkerDeploymentVersion( + deployment_name="llm_srv", + build_id=my_env.build_id), + use_worker_versioning=True, + ), +) +``` + + +```ts +const myWorker = await Worker.create({ +workflowsPath: require.resolve('./workflows'), +taskQueue, +workerDeploymentOptions: { + useWorkerVersioning: true, + version: { buildId: '1.0', deploymentName: 'llm_srv'}, + defaultVersioningBehavior: 'AUTO_UPGRADE', +}, +connection: nativeConnection, +}); +``` + + +```csharp +var myWorker = new TemporalWorker( + Client, + new TemporalWorkerOptions(taskQueue) + {DeploymentOptions = new(new("llm_srv", "1.0"), true) + { DefaultVersioningBehavior = VersioningBehavior.AutoUpgrade }, + }.AddWorkflow()); +``` + + +```ruby +worker = Temporalio::Worker.new( + client: client, + task_queue: task_queue, + workflows: [MyWorkflow], + deployment_options: Temporalio::Worker::DeploymentOptions.new( + version: Temporalio::WorkerDeploymentVersion.new( + deployment_name: 'llm_srv', + build_id: '1.0' + ), + use_worker_versioning: true + ) +) +``` + + + +If your worker and workflows are new, we suggest not providing a `DefaultVersioningBehavior`. +Each workflow author must annotate their workflow as `auto-upgrade` or `pinned` on a workflow-by-workflow basis, based on how long they expect the workflow to run. +If all of your workflows will be short-running for the foreseeable future, you can default to `pinned`. + +Most users who are migrating to rainbow deploys from rolling deploys will start by defaulting to `auto-upgrade` until they have had time to annotate their Workflows. +This default is the most similar to the legacy behavior. +Auto-upgraded workflows won't get stuck on a single version and can use the other Versioning APIs. +Once each workflow type is annotated, you can remove the `DefaultVersioningBehavior`. + +## Rolling out changes with the CLI + +TK TK TK + +You can view the Versions that are active in a Deployment with the CLI: + +```bash +temporal worker deployment describe --name="$MY_DEPLOYMENT" +``` + +To activate a Deployment Version in which the worker is polling TK TK + +```bash +temporal worker deployment set-current-version \ + --version="$MY_DEPLOYMENT_VERSION" +``` + +To gradually ramp a Deployment Version in which the worker is polling, do this: + +```bash +temporal worker deployment set-ramping-version \ + --version="$MY_DEPLOYMENT_VERSION" --percentage=5 +``` + +You should see workflows move to that Version when you do this: + +```bash +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 + +TK TK TK + + + +```go +// w is the Worker configured as in the previous example +w.RegisterWorkflowWithOptions(HelloWorld, workflow.RegisterOptions{ + # or | VersioningBehaviorAutoUpgrade + VersioningBehavior: workflow.VersioningBehaviorPinned, +}) +``` + + +```java +@WorkflowInterface +public interface HelloWorld { + @WorkflowMethod + String hello(); +} + +public static class HelloWorldImpl implements HelloWorld { + @Override + @WorkflowVersioningBehavior(VersioningBehavior.PINNED) + public String hello() { + return "Hello, World!"; + } +} +``` + + +```python +@workflow.defn(versioning_behavior=VersioningBehavior.PINNED) +class HelloWorld: + @workflow.run + async def run(self): + return "hello world!" +``` + + +```ts +setWorkflowOptions({ versioningBehavior: 'PINNED' }, helloWorld); +export async function helloWorld(): Promise { + return 'hello world!'; +} +``` + + +```csharp +[Workflow(VersioningBehavior = VersioningBehavior.Pinned)] +public class HelloWorld +{ + [WorkflowRun] + public async Task RunAsync() + { + return "hello world!"; + } +} +``` + + +```ruby +class HelloWorld < Temporalio::Workflow::Definition + workflow_versioning_behavior Temporalio::VersioningBehavior::PINNED + + def execute + 'hello world!' + end +end +``` + + + +TK TK TK You can see your set of Deployment Versions with: + +```bash +temporal worker deployment describe --name="$MY_DEPLOYMENT" +``` + +## Migrating a pinned Workflow + +TK TK TK + +```bash +temporal workflow update-options \ + --workflow-id="MyWorkflowId" \ + --versioning-override-behavior=pinned \ + --versioning-override-pinned-version="$MY_DEPLOYMENT_VERSION" +``` + +```bash + temporal workflow update-options \ + --query="TemporalWorkerDeploymentVersion=$MY_BAD_DEPLOYMENT_VERSION" \ + --versioning-override-behavior=pinned \ + --versioning-override-pinned-version="$MY_PATCH_DEPLOYMENT_VERSION" +``` + +## Sunsetting an old deployment version + +TK TK TK + +```bash +temporal worker deployment describe-version \ + --version="$MY_DEPLOYMENT_VERSION" +``` + +``` +Worker Deployment Version: + Version llm_srv.1.0 + CreateTime 5 hours ago + RoutingChangedTime 32 seconds ago + RampPercentage 0 + DrainageStatus draining + DrainageLastChangedTime 31 seconds ago + DrainageLastCheckedTime 31 seconds ago + +Task Queues: + Name Type + hello-world activity + hello-world workflow +``` + +### Adding a pre-deployment test + +TK TK TK + + + +```go +workflowOptions := client.StartWorkflowOptions{ +ID: "MyWorkflowId", + TaskQueue: "MyTaskQueue", + VersioningOverride = client.VersioningOverride{ +Behavior: workflow.VersioningBehaviorPinned, +PinnedVersion: "$MY_TEST_DEPLOYMENT_VERSION", + } +} +// c is an initialized Client +we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, HelloWorld, "Hello") +``` + + +```ts +const handle = await client.workflow.start('helloWorld', { +taskQueue: 'MyTaskQueue', +workflowId: 'MyWorkflowId', +versioningOverride: { + pinnedTo: { buildId: '1.0', deploymentName: 'deploy-name' }, +}, +}); +``` + + +```csharp +var workerV1 = new WorkerDeploymentVersion("deploy-name", "1.0"); +var handle = await Client.StartWorkflowAsync( + (HelloWorld wf) => wf.RunAsync(), + new(id: "MyWorkflowId", taskQueue: "MyTaskQueue") + { + VersioningOverride = new VersioningOverride.Pinned(workerV1), + } +); +``` + + +```ruby +worker_v1 = Temporalio::WorkerDeploymentVersion.new( + deployment_name: 'deploy-name', + build_id: '1.0' +) +handle = env.client.start_workflow( + HelloWorld, + id: 'MyWorkflowId', + task_queue: 'MyTaskQueue', + versioning_override: Temporalio::VersioningOverride.pinned(worker_v1) +) +``` + + + +TK TK TK + +```bash +temporal workflow show --workflow-id="MyWorkflowId" +``` + +This covers the complete lifecycle of working with Safe Deploys. +Consider adopting the [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) to provide fine grained, out-of-the-box control of your deployments. \ No newline at end of file diff --git a/package.json b/package.json index c63f4e1c1c..f58375c1cf 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-player": "^2.6.0", "rehype-katex": "7", diff --git a/src/components/elements/SdkTabs/Languages.ts b/src/components/elements/SdkTabs/Languages.ts new file mode 100644 index 0000000000..d755dde3c9 --- /dev/null +++ b/src/components/elements/SdkTabs/Languages.ts @@ -0,0 +1,20 @@ +export const Go = ({ children }) => children; +Go.displayName = 'go'; + +export const Java = ({ children }) => children; +Java.displayName = 'java'; + +export const Python = ({ children }) => children; +Python.displayName = 'py'; + +export const TypeScript = ({ children }) => children; +TypeScript.displayName = 'ts'; + +export const PHP = ({ children }) => children; +PHP.displayName = 'php'; + +export const DotNet = ({ children }) => children; +DotNet.displayName = 'dotnet'; + +export const Ruby = ({ children }) => children; +Ruby.displayName = 'rb'; diff --git a/src/components/elements/SdkTabs/index.js b/src/components/elements/SdkTabs/index.js new file mode 100644 index 0000000000..f00069b048 --- /dev/null +++ b/src/components/elements/SdkTabs/index.js @@ -0,0 +1,75 @@ +import React from 'react'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { SDK_LANGUAGES, LANGUAGE_TAB_GROUP } from '@site/src/constants/sdkLanguages'; + +// Named components for language-specific slots +export const Go = ({ children }) => children; +Go.displayName = 'go'; + +export const Java = ({ children }) => children; +Java.displayName = 'java'; + +export const Python = ({ children }) => children; +Python.displayName = 'py'; + +export const TypeScript = ({ children }) => children; +TypeScript.displayName = 'ts'; + +export const PHP = ({ children }) => children; +PHP.displayName = 'php'; + +export const DotNet = ({ children }) => children; +DotNet.displayName = 'dotnet'; + +export const Ruby = ({ children }) => children; +Ruby.displayName = 'rb'; + +// Main wrapper +const SdkTabs = ({ children }) => { + const contentMap = {}; + + React.Children.forEach(children, (child) => { + if (child?.type?.displayName) { + const langKey = child.type.displayName.toLowerCase(); + contentMap[langKey] = child; + } + }); + + return ( + + {SDK_LANGUAGES.map(({ key, icon: Icon, label }) => ( + }> + {contentMap[key] || ( +
+ {label} example coming soon. +
+ )} +
+ ))} +
+ ); +}; + +SdkTabs.Go = ({ children }) => children; +SdkTabs.Go.displayName = 'go'; + +SdkTabs.Java = ({ children }) => children; +SdkTabs.Java.displayName = 'java'; + +SdkTabs.Python = ({ children }) => children; +SdkTabs.Python.displayName = 'py'; + +SdkTabs.TypeScript = ({ children }) => children; +SdkTabs.TypeScript.displayName = 'ts'; + +SdkTabs.PHP = ({ children }) => children; +SdkTabs.PHP.displayName = 'php'; + +SdkTabs.DotNet = ({ children }) => children; +SdkTabs.DotNet.displayName = 'dotnet'; + +SdkTabs.Ruby = ({ children }) => children; +SdkTabs.Ruby.displayName = 'rb'; + +export default SdkTabs; \ No newline at end of file diff --git a/src/components/index.js b/src/components/index.js index b54c92958b..9d33286540 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -2,7 +2,8 @@ export { default as RetrySimulator } from "./elements/RetrySimulator"; export { Intro } from "./elements/Intro"; export { SdkLogos } from "./elements/SdkLogos"; -export { default as PhotoCarousel } from './elements/PhotoCarousel'; +export { default as PhotoCarousel } from "./elements/PhotoCarousel"; +export { default as SdkTabs } from './elements/SdkTabs'; // Formatting components export { default as DocsTable, NewDocsCell } from "./formatting/DocsTable"; @@ -16,3 +17,6 @@ export { default as DiscoverableDisclosure } from "./info/DiscoverableDisclosure export { default as ToolTipTerm } from "./info/ToolTipTerm"; export { RelatedReadContainer, RelatedReadItem } from "./info/RelatedRead"; export { default as RelatedReadList } from "./info/RelatedReadList"; + +// Extra export +export { default } from './elements/SdkTabs'; \ No newline at end of file diff --git a/src/constants/languageTabs.js b/src/constants/languageTabs.js new file mode 100644 index 0000000000..55c0b814fd --- /dev/null +++ b/src/constants/languageTabs.js @@ -0,0 +1,18 @@ +import { FaJs, FaPython, FaJava } from 'react-icons/fa'; +import { SiGo, SiDotnet, SiTypescript, SiRuby, SiPhp } from 'react-icons/si'; +export const LANGUAGE_TAB_GROUP = 'language'; + +export const LANGUAGE_ICONS = { + go: SiGo, + java: FaJava, + py: FaPython, + ts: SiTypescript, + php: SiPhp, + dotnet: SiDotnet, + rb: SiRuby, +}; + +export const getLanguageLabel = (lang) => { + const Icon = LANGUAGE_ICONS[lang]; + return Icon ? : lang; +}; \ No newline at end of file diff --git a/src/constants/sdkLanguages.js b/src/constants/sdkLanguages.js new file mode 100644 index 0000000000..40c56e5ad5 --- /dev/null +++ b/src/constants/sdkLanguages.js @@ -0,0 +1,14 @@ +import { FaPython, FaJava } from 'react-icons/fa'; +import { SiGo, SiTypescript, SiPhp, SiDotnet, SiRuby } from 'react-icons/si'; + +export const LANGUAGE_TAB_GROUP = 'language'; + +export const SDK_LANGUAGES = [ + { key: 'go', label: 'Go', icon: SiGo }, + { key: 'java', label: 'Java', icon: FaJava }, + { key: 'py', label: 'Python', icon: FaPython }, + { key: 'ts', label: 'TypeScript', icon: SiTypescript }, + { key: 'php', label: 'PHP', icon: SiPhp }, + { key: 'dotnet', label: '.NET', icon: SiDotnet }, + { key: 'rb', label: 'Ruby', icon: SiRuby }, +]; \ No newline at end of file From 7107d23a5d59350bbbae8d96a8a7702fcabc445c Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 15:41:11 -0700 Subject: [PATCH 20/78] clarity edits to safe deploys --- .../worker-deployments/kubernetes-controller.mdx | 9 +++++---- .../worker-deployments/safe-deploys.mdx | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index a2598175cf..8e887dba2c 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -23,11 +23,12 @@ The traditional approach to workflow determinism is to add branches using the [V Over time these checks can become a source of technical debt, as safely removing them from a codebase is a careful process that often involves querying all running workflows. [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. -Using pinning, you will not need to patch most Workflows as part of routine deploys. -If Activities and Workflows are running in the same worker deployment version, you also do not need to ensure interface compatibility across versions. +Using pinning, you will not need to add branching to your Workflows to avoid non-determinism errors. -This greatly simplifies Workflow upgrades, but the cost is that your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. -This is typically known as a rainbow deploy (of which a blue-green deploy is a special case) and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. +This allows you to bypass the other Versioning APIs. +Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. +This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. +A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. This project aims to provide automation to enable rainbow deployments of your workers by simplifying the tracking of which versions still have active workflows, managing the lifecycle of versioned worker deployments, and calling Temporal APIs to update the routing config of Temporal Worker Deployments. This way, you can route Workflow traffic to new versions. diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index a4a6858c75..5b148c9573 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -19,12 +19,12 @@ import { LANGUAGE_TAB_GROUP, getLanguageLabel } from '@site/src/constants/langua import SdkTabs from '@site/src/components'; [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. -Using pinning, you will not need to patch most Workflows as part of routine deploys. -If Activities and Workflows are running in the same worker deployment version, you also do not need to ensure interface compatibility across versions. +Using pinning, you will not need to add branching to your Workflows to avoid non-determinism errors. This allows you to bypass the other Versioning APIs. Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. -This is typically known as a rainbow deploy (of which a blue-green deploy is a special case) and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. +This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. +A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. :::tip Watch this Temporal Replay 2025 talk to learn more about Safe Deploys. @@ -51,9 +51,9 @@ Minimum versions: Self-hosted users: -Minimum Temporal CLI version v1.3.0 -Minimum Temporal Server version: v1.27.1 -Minimum Temporal UI Version v2.36.0 +- Minimum Temporal CLI version v1.3.0 +- Minimum Temporal Server version: v1.27.1 +- Minimum Temporal UI Version v2.36.0 ::: ## Getting Started with Safe Deploys @@ -343,7 +343,7 @@ Task Queues: ### Adding a pre-deployment test -TK TK TK +TK TK TK Canary hooks From 4e08623ba57b25ef21f3d4971ec088c6fd73093e Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Wed, 4 Jun 2025 17:02:09 -0700 Subject: [PATCH 21/78] commit yarn lock to see if it messes up the dprint CI --- yarn.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn.lock b/yarn.lock index a63dfafdeb..624a78983d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9967,6 +9967,11 @@ react-fast-compare@^3.0.1, react-fast-compare@^3.2.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" +react-icons@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.5.0.tgz#8aa25d3543ff84231685d3331164c00299cdfaf2" + integrity sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw== + react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" From e04b48c01ff2b8287a377e3bea5c9ef90d9e77f4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Jun 2025 00:03:04 +0000 Subject: [PATCH 22/78] CI: Automatic .md and .mdx formatting --- .../kubernetes-controller.mdx | 2 +- .../worker-deployments/safe-deploys.mdx | 45 +++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index 8e887dba2c..a329f1e57f 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -28,7 +28,7 @@ Using pinning, you will not need to add branching to your Workflows to avoid non This allows you to bypass the other Versioning APIs. Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. -A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. +A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. This project aims to provide automation to enable rainbow deployments of your workers by simplifying the tracking of which versions still have active workflows, managing the lifecycle of versioned worker deployments, and calling Temporal APIs to update the routing config of Temporal Worker Deployments. This way, you can route Workflow traffic to new versions. diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 5b148c9573..8584cab13c 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -24,9 +24,9 @@ Using pinning, you will not need to add branching to your Workflows to avoid non This allows you to bypass the other Versioning APIs. Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. -A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. +A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. -:::tip +:::tip Watch this Temporal Replay 2025 talk to learn more about Safe Deploys.
@@ -43,6 +43,7 @@ Watch this Temporal Replay 2025 talk to learn more about Safe Deploys. Safe Deploys is currently available in Pre-release. Minimum versions: + - Go SDK version v1.33.0 - Python v1.11 - Java v1.29 @@ -54,14 +55,14 @@ Self-hosted users: - Minimum Temporal CLI version v1.3.0 - Minimum Temporal Server version: v1.27.1 - Minimum Temporal UI Version v2.36.0 -::: + ::: ## Getting Started with Safe Deploys First, we'll introduce some terminology. -- A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. -- A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. +- A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. +- A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. - A **Build ID**, in combination with a Worker Deployment name, identifies a single Worker Deployment Version. - Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to drain pinned workflows or in case you need to roll back. If no current version is specified, the default is unversioned. - Each Worker Deployment can have a **Ramping Version** which is where a configurable percentage of workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no ramping version is specified, 100% of auto-upgrade workflows will go to the Current Version. @@ -161,7 +162,7 @@ worker = Temporalio::Worker.new( version: Temporalio::WorkerDeploymentVersion.new( deployment_name: 'llm_srv', build_id: '1.0' - ), + ), use_worker_versioning: true ) ) @@ -241,13 +242,14 @@ public interface HelloWorld { } public static class HelloWorldImpl implements HelloWorld { - @Override - @WorkflowVersioningBehavior(VersioningBehavior.PINNED) - public String hello() { - return "Hello, World!"; - } +@Override +@WorkflowVersioningBehavior(VersioningBehavior.PINNED) +public String hello() { +return "Hello, World!"; } -``` +} + +```` ```python @@ -256,17 +258,21 @@ class HelloWorld: @workflow.run async def run(self): return "hello world!" -``` +```` + + ```ts setWorkflowOptions({ versioningBehavior: 'PINNED' }, helloWorld); export async function helloWorld(): Promise { return 'hello world!'; } ``` + + ```csharp [Workflow(VersioningBehavior = VersioningBehavior.Pinned)] public class HelloWorld @@ -278,8 +284,10 @@ public class HelloWorld } } ``` + + ```ruby class HelloWorld < Temporalio::Workflow::Definition workflow_versioning_behavior Temporalio::VersioningBehavior::PINNED @@ -289,6 +297,7 @@ class HelloWorld < Temporalio::Workflow::Definition end end ``` + @@ -310,10 +319,10 @@ temporal workflow update-options \ ``` ```bash - temporal workflow update-options \ - --query="TemporalWorkerDeploymentVersion=$MY_BAD_DEPLOYMENT_VERSION" \ - --versioning-override-behavior=pinned \ - --versioning-override-pinned-version="$MY_PATCH_DEPLOYMENT_VERSION" +temporal workflow update-options \ + --query="TemporalWorkerDeploymentVersion=$MY_BAD_DEPLOYMENT_VERSION" \ + --versioning-override-behavior=pinned \ + --versioning-override-pinned-version="$MY_PATCH_DEPLOYMENT_VERSION" ``` ## Sunsetting an old deployment version @@ -406,4 +415,4 @@ temporal workflow show --workflow-id="MyWorkflowId" ``` This covers the complete lifecycle of working with Safe Deploys. -Consider adopting the [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) to provide fine grained, out-of-the-box control of your deployments. \ No newline at end of file +Consider adopting the [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) to provide fine grained, out-of-the-box control of your deployments. From eb32ef274f70795fee258ab2aace03df176c49d7 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:24:10 -0700 Subject: [PATCH 23/78] Update docs/develop/determinism.mdx Co-authored-by: Brian MacDonald --- docs/develop/determinism.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx index 1cc9c1cc38..a68a08b3f5 100644 --- a/docs/develop/determinism.mdx +++ b/docs/develop/determinism.mdx @@ -14,7 +14,7 @@ Making revisions to existing Workflow code can be challenging. Your Workflow cod ## Use Replay Testing before and during your deployments -The best way to verify that your code won't cause non-determinism errors once deployed is to make use of [replay testing](https://docs.temporal.io/workflow-execution#replay). +The best way to verify that your code won't cause non-determinism errors once deployed is to use [replay testing](https://docs.temporal.io/workflow-execution#replay). Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that it is compatible with the provided history. From adcc26931acc54464263b7bd91804934627ea860 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:24:24 -0700 Subject: [PATCH 24/78] Update docs/develop/determinism.mdx Co-authored-by: Brian MacDonald --- docs/develop/determinism.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx index a68a08b3f5..0b4958a8a0 100644 --- a/docs/develop/determinism.mdx +++ b/docs/develop/determinism.mdx @@ -16,7 +16,7 @@ Making revisions to existing Workflow code can be challenging. Your Workflow cod The best way to verify that your code won't cause non-determinism errors once deployed is to use [replay testing](https://docs.temporal.io/workflow-execution#replay). -Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that it is compatible with the provided history. +Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that your new code is compatible with the provided history. There are multiple points in your development lifecycle where running replay tests can make sense. They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. From 58a957b1cabe01c443a88cb7a966b5b4830bc8ac Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:24:49 -0700 Subject: [PATCH 25/78] Update docs/develop/go/versioning.mdx Co-authored-by: Brian MacDonald --- docs/develop/go/versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 52795e4be3..62282077d3 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -99,7 +99,7 @@ Imagine you want to revise this Workflow by adding another Activity to calculate If an existing Workflow Execution was started by the original version of the Workflow code, where `ActivityA` was run, and then resumed running on a new Worker where it was replaced with `ActivityC`, the server side Event History would be out of sync. This would cause the Workflow to fail with a nondeterminism error. -Thus we use `workflow.GetVersion()`: +To avoid this problem, use `workflow.GetVersion()`: ```go var err error From e01e50ae21ff1347a7b0766502d85c36bfd6eb6d Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:26:34 -0700 Subject: [PATCH 26/78] Update docs/encyclopedia/worker-versioning-legacy.mdx Co-authored-by: Brian MacDonald --- docs/encyclopedia/worker-versioning-legacy.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index 884c24c3a0..e0079da5d5 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -95,7 +95,7 @@ You also have the option to specify that the continued Workflow should start usi :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. See [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: From 8c174f2b5947e3f241b6465baf0db77a4a0d0179 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:26:50 -0700 Subject: [PATCH 27/78] Update docs/encyclopedia/worker-versioning-legacy.mdx Co-authored-by: Brian MacDonald --- docs/encyclopedia/worker-versioning-legacy.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index e0079da5d5..5630cf8969 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -220,7 +220,7 @@ This limit is configurable on the server via the `limit.workerBuildIdSize` dynam :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. See [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). ::: From 71fb38a014aba75d016dc23888ae77765f553304 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:29:21 -0700 Subject: [PATCH 28/78] Update docs/production-deployment/worker-deployments/kubernetes-controller.mdx Co-authored-by: Brian MacDonald --- .../worker-deployments/kubernetes-controller.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index a329f1e57f..e45dc2f94b 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -30,7 +30,7 @@ Instead, your deployment system must support multiple versions running simultane This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. -This project aims to provide automation to enable rainbow deployments of your workers by simplifying the tracking of which versions still have active workflows, managing the lifecycle of versioned worker deployments, and calling Temporal APIs to update the routing config of Temporal Worker Deployments. +This feature provides automation to enable rainbow deployments of your workers by simplifying the tracking of which versions still have active workflows, managing the lifecycle of versioned worker deployments, and calling Temporal APIs to update the routing config of Temporal Worker Deployments. This way, you can route Workflow traffic to new versions. Note that in Temporal, **Worker Deployment** is sometimes referred to as **Deployment**, but since the controller makes significant references to Kubernetes Deployment resource, within this page we will stick to these terms: From 5228cadd83054bf4d26cf7d1324c03f767d020cf Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:32:15 -0700 Subject: [PATCH 29/78] Update docs/develop/go/versioning.mdx Co-authored-by: Brian MacDonald --- docs/develop/go/versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 62282077d3..ec0fdb1948 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -93,7 +93,7 @@ func YourWorkflow(ctx workflow.Context, data string) (string, error) { } ``` -Now let's say we replaced `ActivityA` with `ActivityC` and deployed the updated code. +Suppose you replaced `ActivityA` with `ActivityC` and deployed the updated code. Imagine you want to revise this Workflow by adding another Activity to calculate a file checksum. If an existing Workflow Execution was started by the original version of the Workflow code, where `ActivityA` was run, and then resumed running on a new Worker where it was replaced with `ActivityC`, the server side Event History would be out of sync. From 98d49971bc33ac4a7ea06a60d575b952d2c6203d Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 09:56:46 -0700 Subject: [PATCH 30/78] edits based on feedback --- docs/develop/dotnet/versioning.mdx | 6 +++++- docs/develop/go/versioning.mdx | 16 ++++++++++------ docs/develop/java/versioning.mdx | 6 +++++- docs/develop/python/versioning.mdx | 6 +++++- docs/develop/typescript/versioning.mdx | 6 +++++- .../worker-deployments/safe-deploys.mdx | 6 +++--- 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index 67779406bb..f9460ecd1b 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -30,6 +30,7 @@ tags: import { CaptionedImage } from '@site/src/components'; Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. + The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -219,7 +220,10 @@ public class MyWorkflow Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +## Safe Deploys + +Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay-test). diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index ec0fdb1948..923c44f150 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -19,6 +19,7 @@ tags: --- Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. + The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -222,12 +223,15 @@ When `workflow.GetVersion()` is run for a new Workflow execution, it records a m GetVersion allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). -## Sanity checking +## Safe deploys + +Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +## Runtime checking -The Temporal Go SDK performs a runtime sanity check to help prevent obvious incompatible changes. -Adding, removing, or reordering any of these methods without Versioning triggers the sanity check and results in a nondeterminism error: +The Temporal Go SDK performs a runtime check to help prevent obvious incompatible changes. +Adding, removing, or reordering any of these methods without Versioning triggers the runtime check and results in a nondeterminism error: - workflow.ExecuteActivity() - workflow.ExecuteChildWorkflow() @@ -237,7 +241,7 @@ Adding, removing, or reordering any of these methods without Versioning triggers - workflow.SignalExternalWorkflow() - workflow.Sleep() -The sanity check does not perform a thorough check. +The runtime check does not perform a thorough check. For example, it does not check on the Activity's input arguments or the Timer duration. Each Temporal SDK implements these sanity checks differently, and they are not a complete check for non-deterministic changes. -Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. +Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. \ No newline at end of file diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index afc3c4b83c..97bbc8f778 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -20,6 +20,7 @@ tags: --- Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. + The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -241,7 +242,10 @@ Workflow.upsertTypedSearchAttributes(Constants.TEMPORAL_CHANGE_VERSION.valueSet( GetVersion allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +## Safe Deploys + +Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 87a1e0d1f1..168f0f5fe3 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -31,6 +31,7 @@ tags: import { CaptionedImage } from '@site/src/components'; Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. + The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -244,7 +245,10 @@ class MyWorkflow: Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +## Safe Deploys + +Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index 96517d0367..e28fbd6e18 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -21,6 +21,7 @@ tags: import { CaptionedImage } from '@site/src/components'; Since Workflow Executions in Temporal can run for long periods — sometimes months or even years — it's common to need to make changes to a Workflow Definition, even while a particular Workflow Execution is in progress. + The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. @@ -156,7 +157,10 @@ Once you're sure that you will no longer need to [Query](/develop/typescript/mes Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). + +## Safe Deploys + +Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 8584cab13c..8a4eb2782d 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -59,12 +59,12 @@ Self-hosted users: ## Getting Started with Safe Deploys -First, we'll introduce some terminology. +To get started with Safe Deploys, you should understand some concepts around versioning and deployments. - A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. - A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. - A **Build ID**, in combination with a Worker Deployment name, identifies a single Worker Deployment Version. - - Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to drain pinned workflows or in case you need to roll back. If no current version is specified, the default is unversioned. + - Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to allow pinned Workflows to finish executing, or in case you need to roll back. If no current version is specified, the default is unversioned. - Each Worker Deployment can have a **Ramping Version** which is where a configurable percentage of workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no ramping version is specified, 100% of auto-upgrade workflows will go to the Current Version. - You can declare each Workflow type to have a **Versioning Behavior**, either `pinned` or `auto-upgraded`. A `pinned` Worfklow is guaranteed to complete on a single Worker Deployment Version. An `auto-upgraded` Workflow will move to the latest Worker Deployment Version automatically whenever you change the current version. @@ -176,7 +176,7 @@ If all of your workflows will be short-running for the foreseeable future, you c Most users who are migrating to rainbow deploys from rolling deploys will start by defaulting to `auto-upgrade` until they have had time to annotate their Workflows. This default is the most similar to the legacy behavior. -Auto-upgraded workflows won't get stuck on a single version and can use the other Versioning APIs. +Auto-upgraded workflows won't be restricted to a single version and can use the other Versioning APIs. Once each workflow type is annotated, you can remove the `DefaultVersioningBehavior`. ## Rolling out changes with the CLI From 8520afe90b89bbdf9f8f6e0eb24648f81b8c3c99 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Jun 2025 16:57:39 +0000 Subject: [PATCH 31/78] CI: Automatic .md and .mdx formatting --- docs/develop/go/versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 923c44f150..aaea4eed9a 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -244,4 +244,4 @@ Adding, removing, or reordering any of these methods without Versioning triggers The runtime check does not perform a thorough check. For example, it does not check on the Activity's input arguments or the Timer duration. Each Temporal SDK implements these sanity checks differently, and they are not a complete check for non-deterministic changes. -Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. \ No newline at end of file +Instead, you should incorporate [Replay Testing](/develop/go/testing-suite#replay) when making revisions. From 5670e627e729d2a3fdcbf8093113747ef266bd11 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 10:22:11 -0700 Subject: [PATCH 32/78] put php versioning back in tree, fell out by accident --- sidebars.js | 1 + 1 file changed, 1 insertion(+) diff --git a/sidebars.js b/sidebars.js index 3d1e8e4cac..b4dd60821d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -178,6 +178,7 @@ module.exports = { "develop/php/message-passing", "develop/php/cancellation", "develop/php/asynchronous-activity-completion", + "develop/php/versioning", "develop/php/observability", "develop/php/debugging", "develop/php/schedules", From e87be9331f224b55e786626f33157d0070328be6 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Thu, 5 Jun 2025 12:19:35 -0700 Subject: [PATCH 33/78] more feedback edits --- docs/develop/determinism.mdx | 6 +++--- docs/develop/go/versioning.mdx | 14 +++++++------- .../worker-deployments/safe-deploys.mdx | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx index 0b4958a8a0..d0b2924519 100644 --- a/docs/develop/determinism.mdx +++ b/docs/develop/determinism.mdx @@ -10,7 +10,7 @@ tags: - Replay --- -Making revisions to existing Workflow code can be challenging. Your Workflow code must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints). This means your changes to that code have to be as well. Changes to your Workflow code that qualify as non-deterministic need to be protected by either using the [Versioning APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code. +Making revisions to existing Workflow code can be challenging. Your Workflow code must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints). This means your changes to that code have to be as well. Changes to your Workflow code that qualify as non-deterministic need to be protected by using the [Versioning APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code. ## Use Replay Testing before and during your deployments @@ -20,11 +20,11 @@ Replay testing takes one or more existing [Workflow Histories](https://docs.temp There are multiple points in your development lifecycle where running replay tests can make sense. They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. -- During development, replay testing lets you get feedback as early as possible on whether your changes are compatible. For example, you might include some integration tests that run your Workflows against the Temporal Test Server to produce histories which you then check in. You can use those checked-in histories for replay tests to verify you haven't made breaking changes. +- During development, replay testing lets you get feedback as early as possible on whether your changes are compatible. - During pre-deployment validation (such as during some automated deployment validation) you can get feedback in a more representative environment. For example, you might fetch histories from a live Temporal environment (whether production or some kind of pre-production) and use them in replay tests. - At deployment time, your environment _is_ production, but you are using the new code to replay recent real-world Workflow histories. -When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. You can do the same with the pre-merge CI pipeline. However, if you are using encrypted Payloads, which is a typical and recommended setup in production, you may not be able to decrypt the fetched histories. Additionally if your Workflows contain any PII (which should be encrypted), make sure this information is scrubbed for the purposes of your tests, or err on the side of caution and don't use this method. +When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. You can do the same with the pre-merge CI pipeline. However, if you are using encrypted Payloads, which is a typical and recommended setup in production, you may not be able to decrypt the fetched histories. Additionally, if your Workflows contain any personally identifiable information, you should be using a [Failure Converter](https://docs.temporal.io/failure-converter#failure-converter) to ensure that data is encoded. ## Implement a deployment-time replay test diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index aaea4eed9a..7569c77206 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -233,13 +233,13 @@ Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys The Temporal Go SDK performs a runtime check to help prevent obvious incompatible changes. Adding, removing, or reordering any of these methods without Versioning triggers the runtime check and results in a nondeterminism error: -- workflow.ExecuteActivity() -- workflow.ExecuteChildWorkflow() -- workflow.NewTimer() -- workflow.RequestCancelWorkflow() -- workflow.SideEffect() -- workflow.SignalExternalWorkflow() -- workflow.Sleep() +- `workflow.ExecuteActivity()` +- `workflow.ExecuteChildWorkflow()` +- `workflow.NewTimer()` +- `workflow.RequestCancelWorkflow()` +- `workflow.SideEffect()` +- `workflow.SignalExternalWorkflow()` +- `workflow.Sleep()` The runtime check does not perform a thorough check. For example, it does not check on the Activity's input arguments or the Timer duration. diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 8a4eb2782d..dfb783e829 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -64,9 +64,9 @@ To get started with Safe Deploys, you should understand some concepts around ver - A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. - A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. - A **Build ID**, in combination with a Worker Deployment name, identifies a single Worker Deployment Version. - - Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to allow pinned Workflows to finish executing, or in case you need to roll back. If no current version is specified, the default is unversioned. - - Each Worker Deployment can have a **Ramping Version** which is where a configurable percentage of workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no ramping version is specified, 100% of auto-upgrade workflows will go to the Current Version. - - You can declare each Workflow type to have a **Versioning Behavior**, either `pinned` or `auto-upgraded`. A `pinned` Worfklow is guaranteed to complete on a single Worker Deployment Version. An `auto-upgraded` Workflow will move to the latest Worker Deployment Version automatically whenever you change the current version. +- Each Worker Deployment has a single **Current Version** which is where workflows are routed to unless they were previously pinned on a different version. Other versions are still around to allow pinned Workflows to finish executing, or in case you need to roll back. If no current version is specified, the default is unversioned. +- Each Worker Deployment can have a **Ramping Version** which is where a configurable percentage of workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no ramping version is specified, 100% of auto-upgrade workflows will go to the Current Version. +- You can declare each Workflow type to have a **Versioning Behavior**, either `pinned` or `auto-upgraded`. A `pinned` Worfklow is guaranteed to complete on a single Worker Deployment Version. An `auto-upgraded` Workflow will move to the latest Worker Deployment Version automatically whenever you change the current version. Your deployment system should support rainbow deployments so that you can keep versions alive to drain existing workflows. The [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) provides an example of using Kubernetes to bootstrap a rainbow deployment. From ec1672311225ce3f006f9c29541ddae75f8e7d1b Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Fri, 6 Jun 2025 08:51:34 -0700 Subject: [PATCH 34/78] update runtime checking anchor --- docs/develop/go/index.mdx | 2 +- docs/develop/go/versioning.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/develop/go/index.mdx b/docs/develop/go/index.mdx index e4b2d1ad07..b36beda841 100644 --- a/docs/develop/go/index.mdx +++ b/docs/develop/go/index.mdx @@ -99,7 +99,7 @@ Complete Activities asynchronously. Change Workflow Definitions without causing non-deterministic behavior in running Workflows. - [Temporal Go SDK Versioning APIs](/develop/go/versioning#getversion) -- [Sanity checking](/develop/go/versioning#sanity-checking) +- [Runtime checking](/develop/go/versioning#runtime-checking) ## [Observability](/develop/go/observability) diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 7569c77206..e51679187d 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -228,7 +228,7 @@ It is a powerful method for introducing compatible changes without introducing n Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). -## Runtime checking +## Runtime checking {#runtime-checking} The Temporal Go SDK performs a runtime check to help prevent obvious incompatible changes. Adding, removing, or reordering any of these methods without Versioning triggers the runtime check and results in a nondeterminism error: From 98430559960b5aa8e0d11cefc444d1d9eeea6a91 Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Fri, 6 Jun 2025 14:27:59 -0700 Subject: [PATCH 35/78] remove TKs from safe deploys for now --- .../worker-deployments/safe-deploys.mdx | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index dfb783e829..869e8d39ad 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -71,19 +71,15 @@ To get started with Safe Deploys, you should understand some concepts around ver Your deployment system should support rainbow deployments so that you can keep versions alive to drain existing workflows. The [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) provides an example of using Kubernetes to bootstrap a rainbow deployment. -### Opting into the Pre-release - -TK TK TK - -``` -temporal server start-dev \ - --dynamic-config-value frontend.workerVersioningWorkflowAPIs=true \ - --dynamic-config-value system.enableDeploymentVersions=true -``` - ## Configuring a Worker for Safe Deploys -You'll need to TK TK TK +You'll need to add a few additional configuration parameters to your Workers to toggle on Safe Deploys. +There are three new parameters, with different names depending on the language: +- `UseVersioning`: This enables the Safe Deploys functionality for this Worker. +- A `Version` string to identify the revision that this Worker will be allowed to execute. This is a combination of a deployment name and a build ID number. +- The Versioning Behavior, either `pinned` or `auto-upgraded`. + +Follow the example for your SDK below: @@ -181,29 +177,31 @@ Once each workflow type is annotated, you can remove the `DefaultVersioningBehav ## Rolling out changes with the CLI -TK TK TK +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 active in a Deployment with the CLI: +You can view the Versions that are active in a Deployment with `temporal worker deployment describe`: ```bash temporal worker deployment describe --name="$MY_DEPLOYMENT" ``` -To activate a Deployment Version in which the worker is polling TK TK +To activate a Deployment Version, use `temporal worker deployment set-current-version` ```bash temporal worker deployment set-current-version \ --version="$MY_DEPLOYMENT_VERSION" ``` -To gradually ramp a Deployment Version in which the worker is polling, do this: +To ramp a Deployment Version up to some percentage of your overall Worker fleet, use `set-ramping version`. +This requires the [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller). ```bash temporal worker deployment set-ramping-version \ --version="$MY_DEPLOYMENT_VERSION" --percentage=5 ``` -You should see workflows move to that Version when you do this: +You can verify that Workflows are cutting over to that version with `describe -w YourWorkflowID`: ```bash temporal workflow describe -w YourWorkflowID @@ -221,7 +219,8 @@ Versioning Info: ## Marking a Workflow Type as Pinned -TK TK TK +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: @@ -301,7 +300,7 @@ end -TK TK TK You can see your set of Deployment Versions with: +You can check your set of Deployment Versions with `temporal worker deployment describe`: ```bash temporal worker deployment describe --name="$MY_DEPLOYMENT" @@ -309,7 +308,7 @@ temporal worker deployment describe --name="$MY_DEPLOYMENT" ## Migrating a pinned Workflow -TK TK TK +If you need to migrate a pinned Workflow to a new version, use `temporal workflow update-options`: ```bash temporal workflow update-options \ @@ -318,6 +317,8 @@ temporal workflow update-options \ --versioning-override-pinned-version="$MY_DEPLOYMENT_VERSION" ``` +You can migrate several Workflows at once matching a `--query` parameter: + ```bash temporal workflow update-options \ --query="TemporalWorkerDeploymentVersion=$MY_BAD_DEPLOYMENT_VERSION" \ @@ -327,7 +328,14 @@ temporal workflow update-options \ ## Sunsetting an old deployment version -TK TK TK +After a version stops accepting new Workflows, it is considered to be "draining," which is displayed in a value called `DrainageStatus`. +As Workflows pinned to this version complete, the version drains. +Periodically, the Temporal Service will refresh this status by counting any open pinned workflows using that version. +On each refresh, `DrainageInfo.last_checked_time` is updated. +Eventually, `DrainageInfo` will report that the version is fully drained. +At this point, no workflows are still running and no more will be automatically routed to it, so you can consider shutting down the running Workers. + +You can monitor this with `temporal worker deployment describe-version`: ```bash temporal worker deployment describe-version \ @@ -350,9 +358,13 @@ Task Queues: hello-world workflow ``` +If you have implemented [Queries](/sending-messages#sending-queries) on these Workflows, you may need to keep some Workers running to handle them. + ### Adding a pre-deployment test -TK TK TK Canary hooks +Before deploying a new Workflow revision, you can test it with synthetic traffic. + +To do this, utilize pinning in your tests, following the examples below: @@ -408,11 +420,5 @@ handle = env.client.start_workflow( -TK TK TK - -```bash -temporal workflow show --workflow-id="MyWorkflowId" -``` - This covers the complete lifecycle of working with Safe Deploys. Consider adopting the [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) to provide fine grained, out-of-the-box control of your deployments. From 8b502c408feee38a3721cf1471f375ccb7ce7e98 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 6 Jun 2025 21:28:50 +0000 Subject: [PATCH 36/78] CI: Automatic .md and .mdx formatting --- docs/production-deployment/worker-deployments/safe-deploys.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/safe-deploys.mdx index 869e8d39ad..5ebbd94cd1 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/safe-deploys.mdx @@ -75,6 +75,7 @@ The [Temporal Worker Controller](/production-deployment/worker-deployments/kuber You'll need to add a few additional configuration parameters to your Workers to toggle on Safe Deploys. There are three new parameters, with different names depending on the language: + - `UseVersioning`: This enables the Safe Deploys functionality for this Worker. - A `Version` string to identify the revision that this Worker will be allowed to execute. This is a combination of a deployment name and a build ID number. - The Versioning Behavior, either `pinned` or `auto-upgraded`. From 432a68c3fc4f52c0b884e550eb3ae9d55274c64a Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Mon, 16 Jun 2025 09:35:14 -0700 Subject: [PATCH 37/78] handle feedback, rename features --- docs/develop/determinism.mdx | 15 ++++-- docs/develop/dotnet/versioning.mdx | 14 +++--- docs/develop/go/versioning.mdx | 18 +++---- docs/develop/go/worker-versioning-legacy.mdx | 4 +- docs/develop/java/versioning.mdx | 13 ++--- .../develop/java/worker-versioning-legacy.mdx | 4 +- docs/develop/python/versioning.mdx | 13 ++--- .../python/worker-versioning-legacy.mdx | 4 +- docs/develop/typescript/versioning.mdx | 13 ++--- .../typescript/worker-versioning-legacy.mdx | 4 +- .../encyclopedia/worker-versioning-legacy.mdx | 8 ++-- .../workflow/workflow-definition.mdx | 2 +- .../worker-deployments/index.mdx | 3 +- .../kubernetes-controller.mdx | 8 ++-- ...safe-deploys.mdx => worker-versioning.mdx} | 47 +++++++++---------- sidebars.js | 3 +- vercel.json | 2 +- 17 files changed, 90 insertions(+), 85 deletions(-) rename docs/production-deployment/worker-deployments/{safe-deploys.mdx => worker-versioning.mdx} (86%) diff --git a/docs/develop/determinism.mdx b/docs/develop/determinism.mdx index d0b2924519..5fc6cba89d 100644 --- a/docs/develop/determinism.mdx +++ b/docs/develop/determinism.mdx @@ -10,7 +10,10 @@ tags: - Replay --- -Making revisions to existing Workflow code can be challenging. Your Workflow code must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints). This means your changes to that code have to be as well. Changes to your Workflow code that qualify as non-deterministic need to be protected by using the [Versioning APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code. +Temporal Workflows must be [deterministic](https://docs.temporal.io/workflow-definition#deterministic-constraints) in terms of the events that they generate server-side. +Changes to your Workflows that would create different server-side events, or events in a different order, need to be protected by using the [Versioning APIs](https://docs.temporal.io/workflow-definition#workflow-versioning) within your Workflow code. +You can also use [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) to pin your deployments to specific code revisions. +Activities do not need to be deterministic. ## Use Replay Testing before and during your deployments @@ -18,14 +21,18 @@ The best way to verify that your code won't cause non-determinism errors once de Replay testing takes one or more existing [Workflow Histories](https://docs.temporal.io/workflow-execution/event#event-history) that ran against a previous version of Workflow code and runs them against your _current_ Workflow code, verifying that your new code is compatible with the provided history. -There are multiple points in your development lifecycle where running replay tests can make sense. They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. +There are multiple points in your development lifecycle where running replay tests can make sense. +They exist on a spectrum, with shortest time to feedback on one end, and most representative of a production deployment on the other. - During development, replay testing lets you get feedback as early as possible on whether your changes are compatible. - During pre-deployment validation (such as during some automated deployment validation) you can get feedback in a more representative environment. For example, you might fetch histories from a live Temporal environment (whether production or some kind of pre-production) and use them in replay tests. - At deployment time, your environment _is_ production, but you are using the new code to replay recent real-world Workflow histories. -When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. You can do the same with the pre-merge CI pipeline. However, if you are using encrypted Payloads, which is a typical and recommended setup in production, you may not be able to decrypt the fetched histories. Additionally, if your Workflows contain any personally identifiable information, you should be using a [Failure Converter](https://docs.temporal.io/failure-converter#failure-converter) to ensure that data is encoded. +When you're writing changes to Workflow code, you can fetch some representative histories from your pre-production or production Temporal environment and verify they work with your changes. +You can do the same with the pre-merge CI pipeline. +If your Workflows contain any personally identifiable information, you should be using a [Failure Converter](https://docs.temporal.io/failure-converter#failure-converter) to ensure that data is encoded. ## Implement a deployment-time replay test -The key to a successful safe deployment is to break it into two phases: a verification phase, where you’ll run the replay test, followed by the actual deployment of your new Worker code. Refer to the [replay testing](https://docs.temporal.io/workflow-execution#replay) docs of each SDK for implementation details. +The key to a successful safe deployment is to break it into two phases: a verification phase, where you'll run the replay test, followed by the actual deployment of your new Worker code. +Refer to the [replay testing](https://docs.temporal.io/workflow-execution#replay) docs of each SDK for implementation details. diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index f9460ecd1b..d0252e1b9f 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -34,15 +34,15 @@ Since Workflow Executions in Temporal can run for long periods — sometimes mon The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. -There are three primary Versioning methods supported by Temporal: +There are three primary Versioning methods that you can use: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. - [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. +- [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). The Worker Versioning feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. ## Workflow Type Versioning {#type-versioning} -Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid this problem by changing the Workflow Type for the new version. To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. For example, if you had made an incompatible change to the following Workflow Definition: @@ -87,7 +87,6 @@ using var worker = new TemporalWorker( .AddWorkflow()); ``` -The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. The downside of this method is that it does not use any Temporal platform features. It requires you to duplicate code and to update any code and commands used to start the Workflow. This can become impractical over time, depending on how you are providing configuration strings to your deployment. @@ -95,7 +94,8 @@ This method also does not provide a way to introduce versioning to any still-run ## Versioning with Patching {#patching} -Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Patching essentially defines a logical branch for a specific change in the Workflow. +If your Workflow is not [pinned to a specific deployment](/production-deployment/worker-deployments/worker-versioning) or you need to fix a bug in a running workflow, you can patch it. Suppose you have an initial Workflow version called `PrePatchActivity`: @@ -221,9 +221,9 @@ public class MyWorkflow Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Safe Deploys +## Worker Versioning -Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, often avoiding the need for patching. Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay-test). diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index e51679187d..1ad6035e16 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -23,15 +23,15 @@ Since Workflow Executions in Temporal can run for long periods — sometimes mon The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. -There are three primary Versioning methods supported by Temporal: +There are three primary Versioning methods that you can use: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. -- [Branching with GetVersion](#getversion). This method works by adding branches to your code tied to specific revisions. In most other SDKs, it is called patching. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). +- [Workflow Branching with GetVersion](#getversion). This method works by adding branches to your code tied to specific revisions. In most other SDKs, it is called patching. +- [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). The Worker Versioning feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. If you were using this method experimentally prior to summer 2025, refer to the [Worker Versioning Legacy](worker-versioning-legacy) docs. ## Workflow Type Versioning {#type-versioning} -Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid this problem by changing the Workflow Type for the new version. To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. For example, if you had made an incompatible change to the following Workflow Definition: @@ -64,15 +64,15 @@ w.RegisterWorkflow(pizza.PizzaWorkflow) w.RegisterWorkflow(pizza.PizzaWorkflowV2) ``` -The upside of this versioning method is that it is easy to understand at a glance, as it does not really use any Temporal platform features. The downside of this method is that it does not use any Temporal platform features. It requires you to duplicate code and to update any code and commands used to start the Workflow. This can become impractical over time, depending on how you are providing configuration strings to your deployment. This method also does not provide a way to introduce versioning to any still-running Workflows -- it is essentially just a cutover, unlike the `GetVersion` method. -## Branching with GetVersion {#getversion} +## Workflow Branching with GetVersion {#getversion} -Branching with `GetVersion` essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Branching with `GetVersion` essentially defines a logical branch for a specific change in a Workflow. +If your Workflow is not [pinned to a specific deployment](/production-deployment/worker-deployments/worker-versioning) or you need to fix a bug in a running workflow, you can branch it. Consider the following Workflow Definition: @@ -224,9 +224,9 @@ When `workflow.GetVersion()` is run for a new Workflow execution, it records a m GetVersion allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Safe deploys +## Worker Versioning -Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, often avoiding the need for branching. ## Runtime checking {#runtime-checking} diff --git a/docs/develop/go/worker-versioning-legacy.mdx b/docs/develop/go/worker-versioning-legacy.mdx index 44386da853..9afd2813ba 100644 --- a/docs/develop/go/worker-versioning-legacy.mdx +++ b/docs/develop/go/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. @@ -83,7 +83,7 @@ err := workflow.NewContinueAsNewError(ctx, "WorkflowName") :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index 97bbc8f778..278a965435 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -24,15 +24,15 @@ Since Workflow Executions in Temporal can run for long periods — sometimes mon The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. -There are three primary Versioning methods supported by Temporal: +There are three primary Versioning methods that you can use: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. - [Branching with GetVersion](#getversion). This method works by adding branches to your code tied to specific revisions. In most other SDKs, it is called patching. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). +- [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). The Worker Versioning feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. If you were using this method experimentally prior to summer 2025, refer to the [Worker Versioning Legacy](worker-versioning-legacy) docs. ## Workflow Type Versioning {#type-versioning} -Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid this problem by changing the Workflow Type for the new version. To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. For example, if you had made an incompatible change to the following Workflow Definition: @@ -99,7 +99,8 @@ This method also does not provide a way to introduce versioning to any still-run ## Branching with GetVersion {#getversion} -Branching with `Workflow.getVersion` essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Branching with `Workflow.getVersion` essentially defines a logical branch for a specific change in the Workflow. +If your Workflow is not [pinned to a specific deployment](/production-deployment/worker-deployments/worker-versioning) or you need to fix a bug in a running workflow, you can branch it. Consider the following Workflow Definition: @@ -243,9 +244,9 @@ Workflow.upsertTypedSearchAttributes(Constants.TEMPORAL_CHANGE_VERSION.valueSet( GetVersion allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Safe Deploys +## Worker Versioning -Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that GetVersion is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, often avoiding the need for branching. Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). diff --git a/docs/develop/java/worker-versioning-legacy.mdx b/docs/develop/java/worker-versioning-legacy.mdx index 528eb2cb34..a7cd8397aa 100644 --- a/docs/develop/java/worker-versioning-legacy.mdx +++ b/docs/develop/java/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. @@ -81,7 +81,7 @@ private final MyActivity activity = :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 168f0f5fe3..d8c9fcbea3 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -35,15 +35,15 @@ Since Workflow Executions in Temporal can run for long periods — sometimes mon The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. -There are three primary Versioning methods supported by Temporal: +There are three primary Versioning methods that you can use: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. - [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). +- [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). The Worker Versioning feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. If you were using this method experimentally prior to summer 2025, refer to the [Worker Versioning Legacy](worker-versioning-legacy) docs. ## Workflow Type Versioning {#type-versioning} -Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid this problem by changing the Workflow Type for the new version. To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. For example, if you had made an incompatible change to the following Workflow Definition: @@ -93,7 +93,8 @@ This method also does not provide a way to introduce versioning to any still-run ## Versioning with Patching {#patching} -Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Patching essentially defines a logical branch for a specific change in the Workflow. +If your Workflow is not [pinned to a specific deployment](/production-deployment/worker-deployments/worker-versioning) or you need to fix a bug in a running workflow, you can patch it. Suppose you have an initial Workflow version called `pre_patch_activity`: @@ -246,9 +247,9 @@ class MyWorkflow: Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Safe Deploys +## Worker Versioning -Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, often avoiding the need for patching. Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). diff --git a/docs/develop/python/worker-versioning-legacy.mdx b/docs/develop/python/worker-versioning-legacy.mdx index 0df8660e09..638386a9aa 100644 --- a/docs/develop/python/worker-versioning-legacy.mdx +++ b/docs/develop/python/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. @@ -53,7 +53,7 @@ Importantly, when you start this Worker, it won't receive any tasks until you se :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index e28fbd6e18..7141383da7 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -25,15 +25,15 @@ Since Workflow Executions in Temporal can run for long periods — sometimes mon The Temporal Platform requires that Workflow code is [deterministic](/workflow-definition#deterministic-constraints). If you make a change to your Workflow code that would cause non-deterministic behavior on Replay, you'll need to use one of our Versioning methods to gracefully update your running Workflows. With Versioning, you can modify your Workflow Definition so that new executions use the updated code, while existing ones continue running the original version. -There are three primary Versioning methods supported by Temporal: +There are three primary Versioning methods that you can use: - [Workflow Type Versioning](#type-versioning). This is the simplest of the three, and acts more like a cutover than true versioning. It is suitable for short-running Workflows. - [Versioning with Patching](#patching). This method works by adding branches to your code tied to specific revisions. It can be used to revise in-progress Workflows. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). Temporal's Safe Deploys feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](worker-versioning-legacy). +- [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). The Worker Versioning feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. If you were using this method experimentally prior to summer 2025, refer to the [Worker Versioning Legacy](worker-versioning-legacy) docs. ## Workflow Type Versioning {#type-versioning} -Since incompatible changes only affect open Workflow Executions of the same type, you can avoid the problem by changing the Workflow Type for the new version. +Since incompatible changes only affect open Workflow Executions of the same type, you can avoid this problem by changing the Workflow Type for the new version. To do this, you can copy the Workflow Definition function, giving it a different name, and make sure that both names were registered with your Workers. For example, if you had made an incompatible change to the following Workflow Definition: @@ -76,7 +76,8 @@ This method also does not provide a way to introduce versioning to any still-run ## Versioning with Patching {#patching} -Patching essentially defines a logical branch for a specific change in the Workflow, rather than for the entire Workflow Definition itself. +Patching essentially defines a logical branch for a specific change in the Workflow. +If your Workflow is not [pinned to a specific deployment](/production-deployment/worker-deployments/worker-versioning) or you need to fix a bug in a running workflow, you can patch it. Suppose you have an initial Workflow that runs `activityA`: @@ -158,9 +159,9 @@ Once you're sure that you will no longer need to [Query](/develop/typescript/mes Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Safe Deploys +## Worker Versioning -Temporal's [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you find that patching is adding maintainability concerns to your codebase, consider adopting [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, often avoiding the need for patching. Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). diff --git a/docs/develop/typescript/worker-versioning-legacy.mdx b/docs/develop/typescript/worker-versioning-legacy.mdx index 557835a5ee..c233b9f317 100644 --- a/docs/develop/typescript/worker-versioning-legacy.mdx +++ b/docs/develop/typescript/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). See the [Pre-release README](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md) for more information. @@ -53,7 +53,7 @@ Importantly, when you start this Worker, it won't receive any tasks until you se :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: diff --git a/docs/encyclopedia/worker-versioning-legacy.mdx b/docs/encyclopedia/worker-versioning-legacy.mdx index 5630cf8969..e9a9101cef 100644 --- a/docs/encyclopedia/worker-versioning-legacy.mdx +++ b/docs/encyclopedia/worker-versioning-legacy.mdx @@ -16,7 +16,7 @@ tags: - It was not made available in Temporal Cloud - The 2024 draft was available in Cloud on an opt-in basis, and is documented in this [Pre-release README.md](https://github.com/temporalio/temporal/blob/main/docs/worker-versioning.md). -For newer revisions of this feature set, please see [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) instead. +For newer revisions of this feature set, please see [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) instead. ::: @@ -34,7 +34,7 @@ Accomplish this goal by assigning a Build ID (a free-form string) to the code th :::caution -This section is for a deprecated Worker Versioning API. Please redirect your attention to [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. Please redirect your attention to [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: @@ -95,7 +95,7 @@ You also have the option to specify that the continued Workflow should start usi :::caution -This section is for a deprecated Worker Versioning API. See [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. See [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: @@ -220,7 +220,7 @@ This limit is configurable on the server via the `limit.workerBuildIdSize` dynam :::caution -This section is for a deprecated Worker Versioning API. See [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). +This section is for a deprecated Worker Versioning API. See [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). ::: diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 352f5df3f0..5561375812 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -247,7 +247,7 @@ A versioning strategy is even more important if your Workflow Executions live lo - [How to version Workflow code in TypeScript](/develop/typescript/versioning) - [How to version Workflow code in .NET](/develop/dotnet/versioning) -Temporal also has a [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) feature that allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. A previous version of Safe Deploys was called [Worker Versioning](/encyclopedia/worker-versioning-legacy). +Temporal also has a [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature that allows you to tag your Workers and programmatically roll them out in pods tied to specific revisions, so that old Workers can run old code paths and new Workers can run new code paths. If you were using this method experimentally prior to summer 2025, refer to the [Worker Versioning Legacy](/encyclopedia/worker-versioning-legacy) docs. ### Handling unreliable Worker Processes {#unreliable-worker-processes} diff --git a/docs/production-deployment/worker-deployments/index.mdx b/docs/production-deployment/worker-deployments/index.mdx index 714d897321..c8aecd81d0 100644 --- a/docs/production-deployment/worker-deployments/index.mdx +++ b/docs/production-deployment/worker-deployments/index.mdx @@ -25,7 +25,6 @@ The content in this section will provide clarity on real-world deployments that Our Worker Deployments guide provides documentation of Temporal product features that make it easier to scale and revise your Workflows. -- [Safe Deploys](/production-deployment/worker-deployments/safe-deploys) allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. -- The [Temporal Worker Controller](/production-deployment/worker-deployments/kubernetes-controller) helps configure these features for a sample Kubernetes deployment. +[Worker Versioning](/production-deployment/worker-deployments/worker-versioning) allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. You can also refer to our [Code Exchange](https://temporal.io/code-exchange) for community-contributed deployments. diff --git a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx index e45dc2f94b..a667898c32 100644 --- a/docs/production-deployment/worker-deployments/kubernetes-controller.mdx +++ b/docs/production-deployment/worker-deployments/kubernetes-controller.mdx @@ -17,12 +17,12 @@ tags: - Durable Execution --- -Temporal's [deterministic constraints](/workflow-definition#deterministic-constraints) can cause challenges when rolling out or rolling back workflow code changes. +Temporal's [deterministic constraints](/workflow-definition#deterministic-constraints) require consideration when rolling out or rolling back workflow code changes. The traditional approach to workflow determinism is to add branches using the [Versioning APIs](/workflow-definition#workflow-versioning). Over time these checks can become a source of technical debt, as safely removing them from a codebase is a careful process that often involves querying all running workflows. -[Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. +[Worker Versioning](/production-deployment/worker-deployments/worker-versioning) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. Using pinning, you will not need to add branching to your Workflows to avoid non-determinism errors. This allows you to bypass the other Versioning APIs. @@ -43,11 +43,9 @@ Note that in Temporal, **Worker Deployment** is sometimes referred to as **Deplo Refer to [Github](https://github.com/DataDog/temporal-worker-controller/blob/main/internal/README.md) for instructions on how to run the Temporal Worker Controller with Minikube. -More usage details are coming soon. - ## Configuring Worker Lifecycle -To use the Temporal Worker Controller, tag your Workers following the guidance for using [Safe Deploys](/production-deployment/worker-deployments/safe-deploys). This means specifying a `TEMPORAL_DEPLOYMENT_NAME` and a `WORKER_BUILD_ID` in addition to the stock hostname and namespace configuration parameters. +To use the Temporal Worker Controller, tag your Workers following the guidance for using [Worker Versioning](/production-deployment/worker-deployments/worker-versioning). This means specifying a `TEMPORAL_DEPLOYMENT_NAME` and a `WORKER_BUILD_ID` in addition to the stock hostname and namespace configuration parameters. When a new worker deployment version is deployed, the worker controller detects it and automatically begins the process of making that version the new current (default) version of the worker deployment it is a part of. This could happen immediately if `cutover.strategy = AllAtOnce`, or gradually if `cutover.strategy = Progressive`. diff --git a/docs/production-deployment/worker-deployments/safe-deploys.mdx b/docs/production-deployment/worker-deployments/worker-versioning.mdx similarity index 86% rename from docs/production-deployment/worker-deployments/safe-deploys.mdx rename to docs/production-deployment/worker-deployments/worker-versioning.mdx index 5ebbd94cd1..3329475098 100644 --- a/docs/production-deployment/worker-deployments/safe-deploys.mdx +++ b/docs/production-deployment/worker-deployments/worker-versioning.mdx @@ -1,8 +1,8 @@ --- -id: safe-deploys -title: Safe Deploys -sidebar_label: Safe Deploys -description: Use Safe Deploys to pin Workflow revisions to individual Worker Deployment Versions, avoiding the need for branching to support multiple code paths. +id: worker-versioning +title: Worker Versioning +sidebar_label: Worker Versioning +description: Use Worker Versioning to pin Workflow revisions to individual Worker Deployment Versions, avoiding the need for branching to support multiple code paths. slug: /production-deployment/worker-deployments/safe-deploys toc_max_heading_level: 4 keywords: @@ -18,16 +18,15 @@ tags: import { LANGUAGE_TAB_GROUP, getLanguageLabel } from '@site/src/constants/languageTabs'; import SdkTabs from '@site/src/components'; -[Safe Deploys](/production-deployment/worker-deployments/safe-deploys) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. -Using pinning, you will not need to add branching to your Workflows to avoid non-determinism errors. +[Worker Versioning](/production-deployment/worker-deployments/worker-versioning) is a Temporal feature that allows you to pin Workflows to individual versions of your workers, which are called Worker Deployment Versions. This allows you to bypass the other Versioning APIs. Instead, your deployment system must support multiple versions running simultaneously and allow you to control when they are sunsetted. This is typically known as a **rainbow deploy** and contrasts to a rolling deploy in which your Workers are upgraded in place without the ability to keep old versions around. -A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update; our Safe Deploys feature facilitates blue-green deploys. +A **blue-green** deploy is a kind of rainbow deploy that is typically used to gradually roll out a new update. :::tip -Watch this Temporal Replay 2025 talk to learn more about Safe Deploys. +Watch this Temporal Replay 2025 talk to learn more about Worker Versioning.
-## Worker Versioning +### Testing a Workflow for replay safety. + +To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay). -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, avoiding the need for patching. +## Worker Versioning -Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay-test). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index c1b2ef9a9d..5fc2b28ab4 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -220,7 +220,7 @@ It is a powerful method for introducing compatible changes without introducing n ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. ## Runtime checking {#runtime-checking} diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index d1ef860273..ee62dc41e7 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -235,10 +235,10 @@ Workflow.upsertTypedSearchAttributes(Constants.TEMPORAL_CHANGE_VERSION.valueSet( Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Worker Versioning +### Testing a Workflow for replay safety. + +To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. -This way, you can pin your deployments to specific revisions, avoiding the need for patching. +## Worker Versioning -Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index a838cafb96..31327f0050 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -249,9 +249,10 @@ This video provides an in-depth overview of how the `patched()` function works:
-## Worker Versioning +### Testing a Workflow for replay safety. + +To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, avoiding the need for patching. +## Worker Versioning -Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index b9c4bbfb94..1da0057a73 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -149,9 +149,10 @@ Once you're sure that you will no longer need to [Query](/develop/typescript/mes Patching allows you to make changes to currently running Workflows. It is a powerful method for introducing compatible changes without introducing non-determinism errors. -## Worker Versioning +### Testing a Workflow for replay safety. + +To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your deployments to specific revisions, avoiding the need for patching. +## Worker Versioning -Changing the order of any commands in your Workflow code that interact directly with the Temporal Service -- such as calling an Activity or creating a Sleep timer -- will cause a non-determinism error unless you've implemented a versioning solution. -To test whether a new revision will require versioning, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx b/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx index a45b9d56ad..c550d2d69a 100644 --- a/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx +++ b/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx @@ -76,7 +76,7 @@ If a failure occurs, the Workflow Execution picks up where the last recorded eve - [How to use Replay APIs using the Java SDK](/develop/java/testing-suite#replay) - [How to use Replay APIs using the Python SDK](/develop/python/testing-suite#replay) - [How to use Replay APIs using the TypeScript SDK](/develop/typescript/testing-suite#replay) -- [How to use Replay APIs using the .NET SDK](/develop/dotnet/testing-suite#replay-test) +- [How to use Replay APIs using the .NET SDK](/develop/dotnet/testing-suite#replay) ### Commands and awaitables {#commands-awaitables} From 3ccd6169970cf32e6c5f0f5c6d95cb1a0024aefb Mon Sep 17 00:00:00 2001 From: Drew Hoskins Date: Fri, 27 Jun 2025 16:32:04 -0400 Subject: [PATCH 70/78] Capitalize Deployment Version per house style --- docs/cli/worker.mdx | 2 +- docs/develop/dotnet/versioning.mdx | 2 +- docs/develop/go/versioning.mdx | 2 +- docs/develop/java/versioning.mdx | 2 +- docs/develop/python/versioning.mdx | 2 +- docs/develop/typescript/versioning.mdx | 2 +- docs/evaluate/temporal-cloud/limits.mdx | 4 ++-- .../worker-deployments/worker-versioning.mdx | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/cli/worker.mdx b/docs/cli/worker.mdx index 2264870c0b..c2c97424a9 100644 --- a/docs/cli/worker.mdx +++ b/docs/cli/worker.mdx @@ -480,7 +480,7 @@ metadata, or its creation/modification time. temporal worker deployment describe-version [options] ``` -For example, to describe a deployment version in a deployment +For example, to describe a Deployment Version in a deployment `YourDeploymentName`, with Build ID `YourBuildID`, and in the default namespace: diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index 0d47acf70a..2a72230e74 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -229,4 +229,4 @@ To make sure your Workflow doesn't need a patch, or that you've patched it succe ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in Deployment Versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/go/versioning.mdx b/docs/develop/go/versioning.mdx index 5fc2b28ab4..4e1f586e7e 100644 --- a/docs/develop/go/versioning.mdx +++ b/docs/develop/go/versioning.mdx @@ -220,7 +220,7 @@ It is a powerful method for introducing compatible changes without introducing n ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in Deployment Versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. ## Runtime checking {#runtime-checking} diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index ee62dc41e7..8b87cb6479 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -241,4 +241,4 @@ To make sure your Workflow doesn't need a patch, or that you've patched it succe ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in Deployment Versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 31327f0050..34b5671c4c 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -255,4 +255,4 @@ To make sure your Workflow doesn't need a patch, or that you've patched it succe ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in Deployment Versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index 1da0057a73..f9907b2b6b 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -155,4 +155,4 @@ To make sure your Workflow doesn't need a patch, or that you've patched it succe ## Worker Versioning -Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in deployment versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. +Temporal's [Worker Versioning](/production-deployment/worker-deployments/worker-versioning) feature allows you to tag your Workers and programmatically roll them out in Deployment Versions, so that old Workers can run old code paths and new Workers can run new code paths. This way, you can pin your Workflows to specific revisions, avoiding the need for patching. diff --git a/docs/evaluate/temporal-cloud/limits.mdx b/docs/evaluate/temporal-cloud/limits.mdx index 96b55ece51..29feaa3b43 100644 --- a/docs/evaluate/temporal-cloud/limits.mdx +++ b/docs/evaluate/temporal-cloud/limits.mdx @@ -354,6 +354,6 @@ The maximum number of worker deployments that the server allows to be registered The maximum number of versions that the server allows to be registered in a single worker deployments at a given time. Note that unused versions will be deleted by the system automatically when this limit is reached. Defaults to 100. -### Max Task Queues In deployment version limits {#max-task-queues-in-deployment-version-limits} +### Max Task Queues In Deployment Version limits {#max-task-queues-in-deployment-version-limits} -The maximum number of task queues that the server allows to be registered in a single worker deployment version. Defaults to 100. +The maximum number of task queues that the server allows to be registered in a single worker Deployment Version. Defaults to 100. diff --git a/docs/production-deployment/worker-deployments/worker-versioning.mdx b/docs/production-deployment/worker-deployments/worker-versioning.mdx index 48d84b1cc8..7cefbe5ce6 100644 --- a/docs/production-deployment/worker-deployments/worker-versioning.mdx +++ b/docs/production-deployment/worker-deployments/worker-versioning.mdx @@ -67,7 +67,7 @@ Self-hosted users: To get started with Worker Versioning, you should understand some concepts around versioning and deployments. -- A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active deployment versions running at once. +- A **Worker Deployment** is a deployment or service across multiple versions. In a rainbow deploy, a deployment can have multiple active Deployment Versions running at once. - A **Worker Deployment Version** is a version of a deployment or service. It can have multiple Workers, but they all run the same build. - A **Build ID**, in combination with a Worker Deployment name, identifies a single Worker Deployment Version. - You can declare each Workflow type to have a **Versioning Behavior**, either Pinned or Auto-Upgrade. @@ -353,7 +353,7 @@ temporal workflow update-options \ In this scenario, you may also need to use the other [Versioning APIs](/workflow-definition#workflow-versioning) to patch your Workflow. -## Sunsetting an old deployment version +## Sunsetting an old Deployment Version After a version stops accepting new Workflows, it is considered to be "draining," which is displayed in a value called `DrainageStatus`. As Workflows pinned to this version complete, the version drains. From cbea6ea8e66dfb470fcef935dd3732323d7e256c Mon Sep 17 00:00:00 2001 From: Drew Hoskins Date: Tue, 1 Jul 2025 10:19:15 -0700 Subject: [PATCH 71/78] Brian feedback --- docs/develop/dotnet/versioning.mdx | 2 +- docs/develop/java/versioning.mdx | 2 +- docs/develop/python/versioning.mdx | 2 +- docs/develop/typescript/versioning.mdx | 2 +- docs/encyclopedia/workflow/workflow-definition.mdx | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/develop/dotnet/versioning.mdx b/docs/develop/dotnet/versioning.mdx index 2a72230e74..e91c27945e 100644 --- a/docs/develop/dotnet/versioning.mdx +++ b/docs/develop/dotnet/versioning.mdx @@ -225,7 +225,7 @@ This video provides an in-depth overview of how the `patched()` function works: ### Testing a Workflow for replay safety. -To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay). +To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/dotnet/testing-suite#replay). ## Worker Versioning diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/versioning.mdx index 8b87cb6479..b03d94ac79 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/versioning.mdx @@ -237,7 +237,7 @@ It is a powerful method for introducing compatible changes without introducing n ### Testing a Workflow for replay safety. -To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). +To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). ## Worker Versioning diff --git a/docs/develop/python/versioning.mdx b/docs/develop/python/versioning.mdx index 34b5671c4c..5d0c80da2d 100644 --- a/docs/develop/python/versioning.mdx +++ b/docs/develop/python/versioning.mdx @@ -251,7 +251,7 @@ This video provides an in-depth overview of how the `patched()` function works: ### Testing a Workflow for replay safety. -To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). +To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/python/testing-suite#replay). ## Worker Versioning diff --git a/docs/develop/typescript/versioning.mdx b/docs/develop/typescript/versioning.mdx index f9907b2b6b..d10eadec92 100644 --- a/docs/develop/typescript/versioning.mdx +++ b/docs/develop/typescript/versioning.mdx @@ -151,7 +151,7 @@ It is a powerful method for introducing compatible changes without introducing n ### Testing a Workflow for replay safety. -To make sure your Workflow doesn't need a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). +To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/typescript/testing-suite#replay). ## Worker Versioning diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 7938f71b84..b51360422a 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -245,7 +245,7 @@ Temporal offers two Versioning strategies: - [Versioning with patching](#workflow-patching): make sure your code changes are compatible across versions of your Workflow. - [Worker Versioning](#worker-versioning): keep Workers tied to specific code revisions, so that old Workers can run old code paths and new Workers can run new code paths. (Note: If you were using this method experimentally prior to 2025, refer to the [Worker Versioning Legacy](/encyclopedia/worker-versioning-legacy) docs, but note that these are planned for deprecation.) -You can use one strategy, or a combination. +You can use either strategy, or a combination. #### Versioning with Patching {#workflow-patching} @@ -264,7 +264,7 @@ To test, see [Safe Deployments](/develop/safe-deployments.mdx). #### Worker Versioning {#worker-versioning} -To learn more about Worker Versioning, go [here](/production-deployment/worker-deployments/worker-versioning). +To learn more about Worker Versioning, see our [Worker Versioning](/product-deployment/worker-deployments/worker-versioning) page. ### Handling unreliable Worker Processes {#unreliable-worker-processes} From e7e1d4bd492e6f824ca475a0b263c65dab2be12e Mon Sep 17 00:00:00 2001 From: Brian MacDonald Date: Tue, 1 Jul 2025 14:55:02 -0400 Subject: [PATCH 72/78] Update workflow-definition.mdx Fixing broken link --- docs/encyclopedia/workflow/workflow-definition.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index b51360422a..64ca8b6231 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -264,7 +264,7 @@ To test, see [Safe Deployments](/develop/safe-deployments.mdx). #### Worker Versioning {#worker-versioning} -To learn more about Worker Versioning, see our [Worker Versioning](/product-deployment/worker-deployments/worker-versioning) page. +To learn more about Worker Versioning, see our [Worker Versioning](/worker-versioning) page. ### Handling unreliable Worker Processes {#unreliable-worker-processes} From dc0b9e3e2b2403a8f99ca041a484503b21b451ab Mon Sep 17 00:00:00 2001 From: Brian MacDonald Date: Tue, 1 Jul 2025 15:00:18 -0400 Subject: [PATCH 73/78] Update workflow-definition.mdx Fixing link (again) --- docs/encyclopedia/workflow/workflow-definition.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 64ca8b6231..f5ea895afe 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -264,7 +264,7 @@ To test, see [Safe Deployments](/develop/safe-deployments.mdx). #### Worker Versioning {#worker-versioning} -To learn more about Worker Versioning, see our [Worker Versioning](/worker-versioning) page. +To learn more about Worker Versioning, see our [Worker Versioning](production-deployment/worker-deployments/worker-versioning) page. ### Handling unreliable Worker Processes {#unreliable-worker-processes} From 581ec406a8ed20ead4e9a56781c90b34b29bbf9b Mon Sep 17 00:00:00 2001 From: Brian MacDonald Date: Wed, 2 Jul 2025 10:47:54 -0400 Subject: [PATCH 74/78] Update workflow-definition.mdx Reverting PHP link for the time being. --- docs/encyclopedia/workflow/workflow-definition.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index f5ea895afe..6d1abcaf9c 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -256,7 +256,7 @@ To patch: - [How to patch Workflow code in Go](/develop/go/versioning#patching) - [How to patch Workflow code in Java](/develop/java/versioning#patching) - [How to patch Workflow code in Python](/develop/python/versioning#patching) -- [How to patch Workflow code in PHP](/develop/php/versioning#patching) +- [How to patch Workflow code in PHP](/develop/php/versioning#/develop/php/versioning#php-sdk-patching-api) - [How to patch Workflow code in TypeScript](/develop/typescript/versioning#patching) - [How to patch Workflow code in .NET](/develop/dotnet/versioning#patching) From f331097e60d1c94100d53f3bab9dfeb5e263f993 Mon Sep 17 00:00:00 2001 From: Brian MacDonald Date: Wed, 2 Jul 2025 10:52:05 -0400 Subject: [PATCH 75/78] Update workflow-definition.mdx Actually fixing link --- docs/encyclopedia/workflow/workflow-definition.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 6d1abcaf9c..fd7019d737 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -256,7 +256,7 @@ To patch: - [How to patch Workflow code in Go](/develop/go/versioning#patching) - [How to patch Workflow code in Java](/develop/java/versioning#patching) - [How to patch Workflow code in Python](/develop/python/versioning#patching) -- [How to patch Workflow code in PHP](/develop/php/versioning#/develop/php/versioning#php-sdk-patching-api) +- [How to patch Workflow code in PHP](/develop/php/versioning#php-sdk-patching-api) - [How to patch Workflow code in TypeScript](/develop/typescript/versioning#patching) - [How to patch Workflow code in .NET](/develop/dotnet/versioning#patching) From 1cbd7b87441dc8d33e027ef1b5252123db15ab6e Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Tue, 8 Jul 2025 14:23:11 -0700 Subject: [PATCH 76/78] pre-release -> public preview --- .../worker-deployments/worker-versioning.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/production-deployment/worker-deployments/worker-versioning.mdx b/docs/production-deployment/worker-deployments/worker-versioning.mdx index 7cefbe5ce6..2014443052 100644 --- a/docs/production-deployment/worker-deployments/worker-versioning.mdx +++ b/docs/production-deployment/worker-deployments/worker-versioning.mdx @@ -46,7 +46,7 @@ Watch this Temporal Replay 2025 talk to learn more about Worker Versioning. ::: :::note -Worker Versioning is currently available in Pre-release. +Worker Versioning is currently available in Public Preview. Minimum versions: From e8f88de989255ad1bbccf07273901664c571476c Mon Sep 17 00:00:00 2001 From: Alex Garnett Date: Tue, 8 Jul 2025 14:28:06 -0700 Subject: [PATCH 77/78] fix broken anchor after merge --- docs/encyclopedia/workflow/workflow-definition.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 802ae16b8b..f98485d147 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -176,7 +176,7 @@ The following Workflow API calls all can produce Commands, and thus must not be - Signalling or cancelling signals to external Workflow Executions - Scheduling or cancelling Nexus operations - Ending the Workflow Execution in any way (completing, failing, cancelling, or continuing-as-new) -- `Patched` or `GetVersion` calls for Versioning (although they may be added or removed according to the [patching](#patching) rules) +- `Patched` or `GetVersion` calls for Versioning (although they may be added or removed according to the [patching](#workflow-patching) rules) - Upserting Workflow Search Attributes - Upserting Workflow Memos - Running a `SideEffect` or `MutableSideEffect` From 8215b506f18fccf9f34973f59bb6e40e69fa4712 Mon Sep 17 00:00:00 2001 From: Carly de Frondeville Date: Tue, 8 Jul 2025 15:05:56 -0700 Subject: [PATCH 78/78] bump versioning go sdk version and add sdk links --- .../worker-deployments/worker-versioning.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/production-deployment/worker-deployments/worker-versioning.mdx b/docs/production-deployment/worker-deployments/worker-versioning.mdx index 2014443052..54d32cb7bc 100644 --- a/docs/production-deployment/worker-deployments/worker-versioning.mdx +++ b/docs/production-deployment/worker-deployments/worker-versioning.mdx @@ -50,10 +50,10 @@ Worker Versioning is currently available in Public Preview. Minimum versions: -- Go SDK version v1.33.0 -- Python v1.11 -- Java v1.29 -- Typescript v1.12 +- Go SDK version [v1.35.0](https://github.com/temporalio/sdk-go/releases/tag/v1.35.0) +- Python [v1.11](https://github.com/temporalio/sdk-python/releases/tag/1.11.0) +- Java [v1.29](https://github.com/temporalio/sdk-java/releases/tag/v1.29.0) +- Typescript [v1.12](https://github.com/temporalio/sdk-typescript/releases/tag/v1.12.0) - Other SDKs: coming soon! Self-hosted users: