Skip to content

Gradual deployments

Gradual Deployments give you the ability to incrementally deploy new versions of Workers by splitting traffic across versions.

Gradual Deployments

Using gradual deployments, you can:

  • Gradually shift traffic to a newer version of your Worker.
  • Monitor error rates and exceptions across versions using analytics and logging tooling.
  • Roll back to a previously stable version if you notice issues when deploying a new version.

Use gradual deployments

The following section guides you through an example usage of gradual deployments. You will choose to use either Wrangler or the Cloudflare dashboard to:

  • Create a new Worker.
  • Publish a new version of that Worker without deploying it.
  • Create a gradual deployment between the two versions.
  • Progress the deployment of the new version to 100% of traffic.

Via Wrangler

1. Create and deploy a new Worker

Create a new "Hello World" Worker using the create-cloudflare CLI (C3) and deploy it.

Terminal window
npm create cloudflare@latest <NAME> -- --type=hello-world

Answer yes or no to using TypeScript. Answer yes to deploying your application. This is the first version of your Worker.

2. Create a new version of the Worker

To create a new version of the Worker, edit the Worker code by changing the Response content to your desired text and upload the Worker by using the wrangler versions upload command.

Terminal window
npx wrangler versions upload

This will create a new version of the Worker that is not automatically deployed.

3. Create a new deployment

Use the wrangler versions deploy command to create a new deployment that splits traffic between two versions of the Worker. Follow the interactive prompts to create a deployment with the versions uploaded in step #1 and step #2. Select your desired percentages for each version.

Terminal window
npx wrangler versions deploy

4. Test the split deployment

Run a cURL command on your Worker to test the split deployment.

Terminal window
for j in {0..10}
do
curl -s https://$WORKER_NAME.$SUBDOMAIN.workers.dev
done

You should see 10 responses. Responses will reflect the content returned by the versions in your deployment. Responses will vary depending on the percentages configured in step #3.

You can test also target a specific version using version overrides.

5. Set your new version to 100% deployment

Run wrangler versions deploy again and follow the interactive prompts. Select the version uploaded in step 2 and set it to 100% deployment.

Terminal window
npx wrangler versions deploy

Via the Cloudflare dashboard

  1. Log in to the Cloudflare dashboard and select your account.
  2. Go to Workers & Pages.
  3. Select Create application > Hello World template > deploy your Worker.
  4. Once the Worker is deployed, go to the online code editor through Edit code. Edit the Worker code (change the Response content) and upload the Worker.
  5. To save changes, select the down arrow next to Deploy > Save. This will create a new version of your Worker.
  6. Create a new deployment that splits traffic between the two versions created in step 3 and 5 by going to Deployments and selecting Deploy Version.
  7. cURL your Worker to test the split deployment.
Terminal window
for j in {0..10}
do
curl -s https://$WORKER_NAME.$SUBDOMAIN.workers.dev
done

You should see 10 responses. Responses will reflect the content returned by the versions in your deployment. Responses will vary depending on the percentages configured in step #6.

Version affinity

By default, the percentages configured when using gradual deployments operate on a per-request basis — a request has a X% probability of invoking one of two versions of the Worker in the deployment.

You may want requests associated with a particular identifier (such as user, session, or any unique ID) to be handled by a consistent version of your Worker to prevent version skew. Version skew occurs when there are multiple versions of an application deployed that are not forwards/backwards compatible. You can configure version affinity to prevent the Worker’s version from changing back and forth on a per-request basis.

You can do this by setting the Cloudflare-Workers-Version-Key header on the incoming request to your Worker. For example:

Terminal window
curl -s https://$SCRIPT_NAME.$SUBDOMAIN.workers.dev -H 'Cloudflare-Workers-Version-Key: foo'

For a given deployment, all requests with a version key set to foo will be handled by the same version of your Worker. The specific version of your Worker that the version key foo corresponds to is determined by the percentages you have configured for each Worker version in your deployment.

You can set the Cloudflare-Workers-Version-Key header both when making an external request from the Internet to your Worker, as well as when making a subrequest from one Worker to another Worker using a service binding.

Setting Cloudflare-Workers-Version-Key using Ruleset Engine

You may want to extract a version key from certain properties of your request such as the URL, headers or cookies. You can configure a Ruleset Engine rule on your zone to do this. This allows you to specify version affinity based on these properties without having to modify the external client that makes the request.

For example, if your worker serves video assets under the URI path /assets/ and you wanted requests to each unique asset to be handled by a consistent version, you could define the following request header modification rule:

Text in Expression Editor:

starts_with(http.request.uri.path, "/asset/")

Selected operation under Modify request header: Set dynamic

Header name: Cloudflare-Workers-Version-Key

Value: regex_replace(http.request.uri.path, "/asset/(.*)", "${1}")

Version overrides

You can use version overrides to send a request to a specific version of your Worker in your gradual deployment.

To specify a version override in your request, you can set the Cloudflare-Workers-Version-Overrides header on the request to your Worker. For example:

Terminal window
curl -s https://$SCRIPT_NAME.$SUBDOMAIN.workers.dev -H 'Cloudflare-Workers-Version-Overrides: my-worker-name="dc8dcd28-271b-4367-9840-6c244f84cb40"'

Cloudflare-Workers-Version-Overrides is a Dictionary Structured Header.

The dictionary can contain multiple key-value pairs. Each key indicates the name of the Worker the override should be applied to. The value indicates the version ID that should be used and must be a String.

A version override will only be applied if the specified version is in the current deployment. The versions in the current deployment can be found using the wrangler deployments list command or on the Workers Dashboard under Worker > Deployments > Active Deployment.

Example

You may want to test a new version in production before gradually deploying it to an increasing proportion of external traffic.

In this example, your deployment is initially configured to route all traffic to a single version:

Version IDPercentage
db7cd8d3-4425-4fe7-8c81-01bf963b6067100%

Create a new deployment using wrangler versions deploy and specify 0% for the new version whilst keeping the previous version at 100%.

Version IDPercentage
dc8dcd28-271b-4367-9840-6c244f84cb400%
db7cd8d3-4425-4fe7-8c81-01bf963b6067100%

Now test the new version with a version override before gradually progressing the new version to 100%:

Terminal window
curl -s https://$SCRIPT_NAME.$SUBDOMAIN.workers.dev -H 'Cloudflare-Workers-Version-Overrides: my-worker-name="dc8dcd28-271b-4367-9840-6c244f84cb40"'

Gradual deployments for Durable Objects

Due to global uniqueness, only one version of each Durable Object can run at a time. This means that gradual deployments work slightly differently for Durable Objects.

When you create a new gradual deployment for a Durable Object Worker, each Durable Object instance is assigned a Worker version based on the percentages you configured in your deployment. This version will not change until you create a new deployment.

Gradual Deployments Durable Objects

Example

This example assumes that you have previously created 3 Durable Objects and derived their IDs from the names “foo”, “bar” and “baz”.

Your Worker is currently on a version that we will call version “A” and you want to gradually deploy a new version “B” of your Worker.

Here is how the versions of your Durable Objects might change as you progress your gradual deployment:

Deployment config”foo""bar""baz”
Version A: 100%
AAA
Version B: 20%
Version A: 80%
BAA
Version B: 50%
Version A: 50%
BBA
Version B: 100%
BBB

This is only an example, so the versions assigned to your Durable Objects may be different. However, the following is guaranteed:

  • For a given deployment, requests to each Durable Object will always use the same Worker version.
  • When you specify each version in the same order as the previous deployment and increase the percentage of a version, Durable Objects which were previously assigned that version will not be assigned a different version. In this example, Durable Object “foo” would never revert from version “B” to version “A”.
  • The Durable Object will only be reset when it is assigned a different version, so each Durable Object will only be reset once in this example.

Observability

When using gradual deployments, you may want to attribute Workers invocations to a specific version in order to get visibility into the impact of deploying new versions.

Logpush

A new ScriptVersion object is available in Workers Logpush. ScriptVersion can only be added through the Logpush API right now. Sample API call:

Terminal window
curl -X POST 'https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/logpush/jobs' \
-H 'Authorization: Bearer <TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"name": "workers-logpush",
"output_options": {
"field_names": ["Event", "EventTimestampMs", "Outcome", "Logs", "ScriptName", "ScriptVersion"],
},
"destination_conf": "<DESTINATION_URL>",
"dataset": "workers_trace_events",
"enabled": true
}'| jq .

ScriptVersion is an object with the following structure:

scriptVersion: {
id: "<UUID>",
message: "<MESSAGE>",
tag: "<TAG>"
}

Runtime binding

Use the Version metadata binding in to access version ID or version tag in your Worker.

Limits

Deployments limit

You can only create a new deployment with the last 10 uploaded versions of your Worker.