Back to Blog

Language: English

The Deploy Succeeded, but the Revision Never Switched

Cloud Run falls back to the previous revision when a new one fails to start, yet gcloud run deploy still exits successfully — so CI stays green while traffic never switches. Fixed by pinning revision suffixes, verifying the created revision, and routing traffic explicitly with update-traffic.

I set up a CD pipeline that automatically reflects merges into develop onto the dev environment. While doing that, I noticed the deploy was being reported as successful even though the revision had never switched.

Deploys That Report Success

When a new revision fails to start, Cloud Run falls back to the old revision to protect users from the impact. That behavior itself is correct.

The problem was that in that case gcloud run deploy still finishes as a success. GitHub Actions goes green. It looks like the merged changes took effect. In reality, traffic is still on the old revision.

There is no signal telling you the deploy failed. You won’t know until the next change lands or somebody happens to test it.

As a countermeasure, I added a step where we verify the switch ourselves.

revision suffix を固定

作成された revision が期待値と一致するか照合

gcloud run services update-traffic で expected revision = 100%

切り替わらなければ workflow を fail

The revision suffix is decided on our side. After the deploy, we check whether the revision that was created has the expected name. On top of that, we explicitly route 100% of traffic to that revision. If it can’t be routed, the workflow fails.

Exit Codes and the Actual State

What was wrong was the very state of affairs where the CD reported “success.” gcloud run deploy did succeed at its own job. It created a new revision, accepted the outcome of Cloud Run playing it safe, and exited normally. It wasn’t lying.

What we actually want to verify is whether the intended revision is running. A command completing without error is merely a proxy for that. Ordinarily the two coincide, so I ended up building the pipeline without distinguishing them.

The same pattern shows up outside deploys too. Cases like submitting a migration job that never gets applied, or Terraform apply passing while the actual resources remain unchanged. If you trust nothing but the exit codes of automation, failures like these linger quietly.

Double Ownership Between Terraform and CD

  • Ownership of the migrate job sat with both Terraform and CD and their updates conflicted, so I separated them
  • For update conflicts that remained anyway, I added retries with exponential backoff
  • Removed the leading target apply from the Terraform CD
  • The Cloud Run runtime template was managed in two places, so ownership was unified under the app deploy side
  • Narrowed what the dev CD runs to the safe side

Every one of these came from having multiple paths for applying changes. When the same resource can be written from two places, remembering which one is correct becomes a job for humans.


Based on what I presented at our achievements presentation on July 31, 2026.