Previews, canaries and traffic¶
runway derives the traffic split from the live service on every deploy (no state file):
| Deploy | New revision | Everything else |
|---|---|---|
runway deploy |
100% (follows latest) |
preview URLs kept, pointing at their revisions |
runway deploy --preview NAME |
0%, URL https://NAME---SERVICE-...run.app |
what was serving is pinned to its revision(s) and keeps serving |
runway deploy --traffic 10 |
10%, URL https://canary---... |
the rest keeps its current split, scaled to 90% |
A preview (or canary) always runs in its own revision, even when its code
and configuration are identical to what serves production (a template
annotation runway.dev/preview: NAME, or runway.dev/canary, makes the
revision distinct). Without that, its URL would point at the production
revision. Only the main deploy (no flag) gets the traffic, and --traffic N
changes how much.
NAME can be a branch name: feature/Login_v2 becomes the tag
feature-login-v2 (shortened with a hash when the tag and the service name
would exceed 46 characters). Redeploying the same branch moves its URL to the
new revision. A deploy whose revision template did not change (for example a
traffic-only or ingress-only change) sends the live template back untouched,
so Cloud Run creates no revision.
Typical CI (GitLab):
deploy-branch: # every branch: its own URL, no traffic
script: runway deploy --stage prod --preview "$CI_COMMIT_REF_NAME"
rules: [{ if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH' }]
deploy-main: # merged: the release gets the traffic,
variables: { GIT_DEPTH: 0 } # then the previews of merged branches go
script:
- runway deploy --stage prod
- runway preview prune --stage prod --yes --delete-revisions
rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' }]
stop-branch: # one branch, by hand
script: runway preview delete --stage prod "$CI_COMMIT_REF_NAME" --yes
when: manual
Canary on main: runway deploy --stage prod --traffic 10, watch, then
runway traffic --stage prod --promote (or --traffic 50 first, or roll back
with runway traffic --stage prod --set <previous-revision>=100).
Previews share the service: service-level settings (ingress, IAP, public
access, tags) and grants come from the branch's runway.yaml like any deploy.
The first deploy of a stage serves the deployed revision whatever the flag
(there is nothing else to serve).
Managing previews¶
$ runway preview list --stage prod
$ runway preview delete --stage prod feature/login # dry run
$ runway preview delete --stage prod feature/login --yes # remove its URL
$ runway preview prune --stage prod # dry run
$ runway preview prune --stage prod --yes --delete-revisions
deleteaccepts branch names (feature/login) or tags (feature-login).runway undeploy --preview NAME --yesandrunway traffic --remove-tagdo the same for one name.prunereads the branches with git in the directory ofrunway.yaml(aftergit fetch --prune, unless--no-fetch) and removes the previews whose branch was merged into the base branch (--base, default: the remote's default branch, then$CI_DEFAULT_BRANCH, thenmain) or no longer exists on the remote (--only-mergedkeeps those). Merge detection needs the full history (GIT_DEPTH: 0in GitLab,fetch-depth: 0in GitHub Actions); deleted branches are detected in shallow clones too.- Only previews created by
deploy --previeware pruned (their revision carries arunway.dev/previewmarker);canaryand other tags are kept. - Without
--yesnothing changes; all removals happen in one traffic update (no new revision). --delete-revisionsalso deletes each preview's revision once nothing points at it: never the latest revisions, never a revision that still has traffic or another tag, and only if it carries the preview marker (the delete is conditioned on the revision's etag). Without it, preview revisions stay in the service's revision list.