Hedronite · Cert Lesson · GCP PCA · Fri 2026-10-16

GCP PCA: Cloud Run revisions traffic splits, tags, and the rollback that does not redeploy

A new image is a revision. A release is a traffic table.

Lesson Class: Cert (GCP PCA)
Track: Cloud track · day 86
Referent: update-traffic · --no-traffic · LATEST · tags
Not a repeat: not 09-28 Pub/Sub · 09-13 GCS lifecycle · 08-20 MIG/LB
Paired Ops: uv/maturin PyO3 packaging + Nix gate
Pin the Revision
Rollback retargets traffic, not a rebuild.
Splits Stick
A manual split survives the next deploy.
Tags Are Not Free
Revision-level mins still warm tagged revisions.
The bad revision was still Ready. Only the percentage changed.

A new container image is not a release. On Cloud Run, a release is a traffic assignment across immutable revisions, and the exam expects you to move that traffic on purpose.

The problem

You operate a service on Google Cloud Run. Deployments look healthy: every gcloud run deploy succeeds, the latest revision shows Ready, and the URL returns 200. Then a bad image ships. You "roll back" by redeploying an older tag from Artifact Registry, which builds a new revision that happens to contain old bits. Or you split traffic in a console click, forget that the split becomes sticky for later deploys, and watch the next hotfix land at 5% forever. Or you tag a revision for load tests, leave minimum instances at the revision level, and pay for idle capacity you thought was free.

Professional Cloud Architect scenarios care about this surface because Cloud Run is a common compute choice for HTTP services, and the control plane makes revision and traffic first-class. The skill is not memorizing button labels. The skill is stating which object is immutable, which object carries percentages, and which command changes routing without rebuilding.

The idea, in plain words

Every deploy creates a revision: an immutable snapshot of the service configuration and container. Traffic is a separate table that sends percentages of requests to one or more revisions (or to "latest ready"). You roll out gradually by deploying with no traffic, then raising the percentage. You roll back by pointing 100% at a previous revision name. You test without serving customers by attaching a tag, which gives that revision its own URL. None of those moves requires rebuilding the image you already trust.

Concept A: revisions are immutable; traffic is the dial

Definition. A revision is a fixed, named generation of a Cloud Run service. Traffic targets map percentages (and optional tags) onto revision names or onto the service's latest ready revision.

Why. If the running configuration could mutate in place, "rollback" would mean hoping the old process comes back. Cloud Run keeps old revisions and lets you retarget traffic. Official docs state that you can send all, none, or some traffic to a revision, gradually roll out, split across revisions, and roll back. Revisions that receive no requests do not consume resources and are not billed, unless minimum instances keep them warm.

Exported shape (percentages must sum to 100):

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: orders-api
spec:
  template:
    metadata:
      name: orders-api-00042-canary
    spec:
      containers:
        - image: us-docker.pkg.dev/cloudrun/container/hello
  traffic:
    - revisionName: orders-api-00041-stable
      percent: 95
    - revisionName: orders-api-00042-canary
      percent: 5
      tag: canary

Walk-through: template describes the next revision to create when you deploy. traffic is independent: here 95% stays on the stable revision name, 5% goes to the canary revision, and tag: canary exposes a dedicated URL for that target. The REST TrafficTarget type makes revisionName and latestRevision mutually exclusive: you either pin a name or float with latest ready, not both on one row.

Common mistake. Reading "latest" in the console as "whatever I built last week." latestRevision: true (or LATEST / --to-latest) means the service's current latest ready revision, which moves when a new revision becomes ready. Spot it when a gradual rollout unexpectedly jumps after an unrelated deploy because traffic still floated to LATEST.

Concept B: gradual rollout, sticky splits, and rollback without rebuild

Definition. A gradual rollout deploys a revision at 0% (or a small percent), then raises its share after observation. A sticky split is the documented lifecycle rule: once you split or pin traffic away from pure-latest behavior, later deployments keep that pattern until you explicitly send traffic to latest again.

Why. Shipping 100% on every image digest couples build success to customer impact. Separating deploy from release lets you prove the new revision under production load. The DevOps Handbook describes the canary release pattern as promoting to successively larger environments only while the software operates as designed, rolling back when it does not. Google SRE frames canarying as testing a new release on a small subset of a typical workload and asks how long and how large the canary should be; the architect's job is to make that dial explicit in the traffic table rather than informal.

Gradual path from the official Cloud Run docs and the gcloud help text verified on the lab workstation (Google Cloud SDK 550.0.0):

# Deploy the candidate without serving customers
gcloud run deploy orders-api --image IMAGE --no-traffic

# Send a small share (LATEST means the newest ready revision)
gcloud run services update-traffic orders-api --to-revisions=LATEST=5

# Raise after the canary looks clean
gcloud run services update-traffic orders-api --to-revisions=LATEST=25

# Rollback: pin 100% to a known-good revision name (no new build required)
gcloud run services update-traffic orders-api \
  --to-revisions=orders-api-00041-stable=100

# Return to "always serve whatever is latest ready"
gcloud run services update-traffic orders-api --to-latest

Rollback YAML that only retargets traffic:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: orders-api
spec:
  traffic:
    - revisionName: orders-api-00041-stable
      percent: 100

Critical exam-facing facts from the rollout docs:

Common mistake. Equating "redeploy the old image tag" with "rollback." Redeploy creates a new revision. Rollback, in the Cloud Run sense, is update-traffic (or an equivalent traffic block) to an existing revision name. Spot it in a design review when the rollback runbook's first step is docker build or gcloud builds submit.

Concept C: tags for testing without customer traffic

Definition. A traffic tag attaches a stable URL prefix to a specific revision target so you can invoke that revision without allocating it a percentage of the primary service hostname.

Why. You often need production configuration (secrets, VPC connectors, service identity) without production customers. Tags give you a dedicated URL such as https://canary---orders-api-....a.run.app while the primary hostname still serves the stable split. Official docs describe a typical sequence: test in staging, deploy to production with --no-traffic --tag TAG, exercise the tagged URL, then migrate percentage with --to-tags.

gcloud run deploy orders-api --image IMAGE --no-traffic --tag canary
gcloud run services update-traffic orders-api --to-tags=canary=5
gcloud run services update-traffic orders-api --remove-tags=canary

Billing note from the docs: if minimum instances are set at the service level, tags do not allocate minimum instances for tagged revisions. If minimum instances are set at the revision level, tagged revisions do get those instances. Leaving a forgotten tag on a revision with revision-level mins is a cost leak. Revisions at 0% can still be deleted; Cloud Run then tries to remove associated tags, and stale tag references can break later traffic updates.

Common mistake. Assuming a tagged revision is "free because it is at 0%." Check where minimum instances are configured before you celebrate. Spot it on the bill as warm instances for a revision that never appears in the primary traffic pie chart.

Putting it together

Architect a Cloud Run release for orders-api:

  1. Keep the serving revision pinned or at 100% latest only when you intentionally want every ready deploy to take all traffic.
  2. For a risky change: deploy with --no-traffic (optionally --tag canary), call the tagged URL with synthetic or mirrored traffic, then update-traffic to 5%, then raise, then either finish at 100% or --to-latest if you want future deploys to float again.
  3. For an incident: identify the last known-good revision name, send it 100% with update-traffic, and only rebuild if that revision itself is wrong for the current dependency world (schema, secrets, IAM).
  4. Write the sticky-split rule into the runbook: after any manual split, the next deploy will not "fix" the release process unless someone restores latest behavior.

That is the PCA lens: compute choice (Cloud Run) plus release mechanics (revisions and traffic) plus operational risk (rollback without health re-check, canary sizing, tag costs).

Check yourself

  1. What is the difference between a Cloud Run revision and a traffic target, and which one do you change to roll back without rebuilding?
  2. You deployed with --no-traffic, then set LATEST=10. A teammate deploys again before you finish the rollout. What happens to traffic if you never called --to-latest, and why?
  3. Why does the documentation warn that rolling traffic back does not re-run deployment health checks?
  4. When do tagged revisions allocate minimum instances, and when do they not?
  5. A design doc says "rollback = redeploy previous image digest." What Cloud Run-native alternative should you propose, and what risk remains even then?

Sources