The answer. wrangler deploy is all-or-nothing: the new version takes 100% of traffic the moment it lands. Gradual deployments separate the two steps. wrangler versions upload builds and uploads a version that receives no traffic; wrangler versions deploy creates a deployment that splits requests by percentage between the current version and the new one. Start at 0% and hit the new version on purpose with the Cloudflare-Workers-Version-Overrides header, then 10%, then 100%; every step is one command, and rollback is the same command pointing back. A deployment can hold at most two versions, and only the last 100 uploads are deployable.
The pattern.
npx wrangler versions upload # -> Version ID: 2a1f... (0% traffic)
npx wrangler versions deploy # interactive: old 100% / new 0%
curl -s https://api.example.com/health \
-H 'Cloudflare-Workers-Version-Overrides: my-api="2a1f..."' # smoke test the 0% version
npx wrangler versions deploy # old 90% / new 10%; watch logs by version
npx wrangler versions deploy # new 100%
Cloudflare-Workers-Version-Key: <user-id> # version affinity: one user always hits the same version
Watch out.
- Random per-request splits cause version skew for a browser that loads assets across two versions. Send a stable
Cloudflare-Workers-Version-Key(a session id) from the client or your edge layer. - The override header only works for versions present in the current deployment; that is why the 0% slot exists.
- Bindings and vars are part of a version. A split deployment can be running two different configs; diff them before you trust a comparison.
Related: production-canary-version-pinned-cutover · deploy-with-rollback-target-health-probe · workers-logs-for-last-week-wrangler-tail-for-now