Jorge Turbica / blog · Blog ← All articles ES · Leer en español
Cloud

Compute Engine pins its API by date: 2026-09-01 is a contract that won't break

Compute Engine's API gets dated versions in GA: defaults like partial success change, and your SDK version now picks the API version.

An AggregatedList call that fails outright today because one zone is having trouble will start returning whatever did answer, but only if your client asks for the new API version. As of November 5, 2026, Compute Engine offers dated, immutable API versions in general availability, and the first stable one, 2026-09-01, is a contract Google commits not to break.

If you automate VM fleets with scripts, SDKs or Terraform, this matters for two reasons: defaults can now evolve without surprising /v1 users, and an SDK upgrade is now also an API version change.

From channels to dated versions

Until now Compute Engine evolved through long-lived channels (/v1, /beta and /alpha) that were updated in place. Google calls this channel-based versioning (CBV) and is replacing it with interface-based versioning (IBV), aligned with AIP-185:

TypeFormatCadenceLifespan
Stable2026-09-01Quarterly, starting with 2026-09-01No breaking changes after release; no end-of-support date
Preview2026-10-01-previewAs neededOne year
/v1Unchanged—Still supported and still the default

The versioning guide adds two details: stable versions are maintained "in perpetuity" under Google Cloud's standard deprecation policy, and features shipped through IBV won't be available in /v1. Migrating isn't required, but staying on /v1 means missing whatever comes next.

What you get with a dated version

Google gives three examples of behavior that /v1 can't change without breaking someone:

  • Fleet-wide listings that tolerate failures. In /v1, AggregatedList defaults returnPartialSuccess to false, so one zone's problem fails the whole fleet query. Dated versions enable partial success by default.
  • Structured errors. Errors follow AIP-193, with google.rpc.ErrorInfo and reason, domain and metadata fields. Ask for a version that doesn't exist and metadata lists supported_versions.
  • Security. New versions can tighten overly broad IAM checks and ship safer defaults.

How to pick a version

The base path is still /compute/v1/; the version goes in the X-Goog-Api-Version header or the $apiVersion query parameter:

bash
curl -X GET \
  "https://compute.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/instances" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "X-Goog-Api-Version: 2026-09-01"

Each version has its own discovery document, such as https://www.googleapis.com/discovery/v1/apis/compute/2026-09-01/rest. Everywhere else, no code changes are needed:

  • SDKs (Python, Go, Java, Node.js, C#, Ruby, PHP): each release binds to a dated version and keeps the v1 namespace (compute_v1, apiv1), so imports stay the same.
  • gcloud: gcloud compute uses the bundled stable version, and the new gcloud preview compute group uses the preview one. Scripts using beta and alpha keep working. Just run gcloud components update.
  • Terraform: the google provider targets stable versions and google-beta targets previews; you only bump the provider version, with nothing to configure in HCL.

The version in use is recorded in Cloud Audit Logs under protoPayload.requestMetadata.callerSuppliedUserAgent, so you can find out which automation is still on /v1.

Azure has always worked this way, but it's mandatory there

The model resembles Azure Resource Manager, where every request carries a dated api-version parameter (2016-02-01, 2014-04-01-preview). The difference is that Azure requires it, while in Compute Engine it's optional and leaving it out keeps you on /v1. That makes adoption gentler, at a price: your code can go years without picking up the improvements, and nobody notices.

The catch: the version ships with the library

Upgrade the SDK or the Terraform provider and you switch API versions, inheriting the new defaults. returnPartialSuccess is the one that worries me most: an inventory or cleanup script that assumed a listing was either complete or an error can now get a list missing a zone, with nothing failing. If that script decides what to delete or recreate by diffing against an expected state, a partial response can trigger the wrong action. Before upgrading, find where you use aggregated listings, pin the SDK version in your dependencies and test against the preview in a non-production project.

Sources

Jorge Turbica

Software Engineer and SRE. I write about the real challenges I run into in production.

See portfolio ↗