Versioning is a migration tool, not a substitute for compatibility. A contract includes schemas, defaults, errors, ordering, authorization, limits, and side effects. This migration runbook classifies a proposed order-response change, introduces a coherent V2, operates both versions, and retires V1 only after traffic proves its owners have moved.
The core idea
Versioning creates a temporary compatibility boundary for behavior that cannot evolve additively. It works only with a change taxonomy, visible negotiation, parallel operation, consumer evidence, and a retirement plan. A version label without those disciplines merely gives incompatibility a name.
Decision point: breaking or additive
The question is not which option is fashionable. Changing defaults or narrowing input is breaking; adding output can still break exhaustive clients. Choose by score every observable behavior, not only schema syntax, and record the assumption that would cause the choice to change.
| Change | Risk |
|---|---|
| Optional request field | Usually compatible |
| New enum output | Client-dependent |
| Rename/remove field | Breaking |
| Different sort default | Breaking |
| New error status | Behavioral risk |
The comparison should include steady-state cost, failure behavior, migration effort, and the skills of the team operating it. Run old SDKs and recorded consumer contracts before committing. If the specification omits a behavior clients actually use, the option's apparent simplicity has moved complexity into operations. Use deserialization, fallback, and unknown-enum errors as the review signal after real traffic arrives.
Runbook phase: inventory consumers and behavior
Objective. Identify who calls which route and which undocumented assumptions matter.
Procedure. combine gateway telemetry, SDK versions, owner interviews, and support history
Record client identity, route, version, last seen, business criticality, and owner. Include monthly jobs and offline devices so a quiet week does not imply zero use.
Name the person authorized to stop the phase and make every command repeatable. Before proceeding, complete synthetic known clients against the inventory pipeline. Stop rather than improvise if traffic has no client identity or retention is shorter than a business cycle. The dashboard for this phase should expose unknown callers, last-seen distribution, and route/version use. Capture start and finish checkpoints so another operator can determine exactly how far the run advanced.
On the wire: choose one negotiation surface
Paths are visible; media types preserve URLs but complicate caches. Protocol participants cannot rely on shared memory or good intentions, so define one mechanism, a default, and correct cache variation
GET /orders/7 HTTP/1.1
Accept: application/vnd.example.order+json;version=2If representation depends on Accept, responses and intermediaries need appropriate Vary: Accept behavior.
Every field or status in that exchange needs one owner and one interpretation. Unknown, duplicated, expired, and reordered input must have defined handling. Specifically test CDN behavior for every supported representation. A subtle interoperability failure occurs when header, path, and query versions combine into untestable variants. Useful telemetry includes requests, cache hits, and missing-version defaults, tagged by peer, route, and deployed contract version without exposing credentials.
Data flow: version adapters around one capability
Follow one logical operation. Transport versions need not duplicate the order engine. At each arrow, translate each representation at the boundary and fork domain behavior only when semantics differ
flowchart LR
V1[V1 JSON]-->A1[V1 adapter]
V2[V2 JSON]-->A2[V2 adapter]
A1-->O[Order capability]
A2-->O
O-->D[(Orders)]V1 customer_name and V2 customer.displayName can map to one internal identity.
The diagram is a map of failure and ownership boundaries, not decoration. Annotate where data becomes durable, where it can be duplicated, and where ordering can change. Validate it with shared domain cases plus boundary-specific fixtures. The model is wrong if version checks spread through policy code and fixes diverge. Correlate adapter failures and normalized outcome differences across the flow using a safe operation identifier.
Release gate: parallel operation and canary
Two versions double selected tests, capacity paths, and support obligations. Ship it by route identified cohorts, compare normalized outcomes, and retain rollback-safe data
5% internal clients -> V2
then 5% external opt-in -> V2
compare errors/latency/outcomes
expand only after one workload cycleMirroring is safe only for read-only or explicitly suppressed side effects.
A rollback is useful only while old code can safely understand new data and side effects already produced. Prove rolling versions, failover, and both dependency paths before increasing exposure. Pause the rollout when V2 writes data V1 cannot read. Compare SLOs and business outcomes split by version/client between cohorts and keep the change reversible until the evidence covers normal load, retries, and at least one dependency disturbance.
Runbook phase: sunset V1
Objective. An announcement does not migrate a caller.
Procedure. contact observed owners, publish examples, emit deprecation guidance, rehearse rejection, then enforce
Sunset: Sat, 31 Oct 2026 23:59:59 GMT
Link: <https://api.example.com/migrations/v2>; rel="deprecation"Use a date only when the organization is prepared to honor and enforce it; the header complements direct communication.
Name the person authorized to stop the phase and make every command repeatable. Before proceeding, complete cutoff in non-production and a controlled exception path. Stop rather than improvise if old clients silently route into incompatible semantics or emergency rollback code is gone. The dashboard for this phase should expose deprecated calls by owner, blockers, post-sunset traffic, and exceptions. Capture start and finish checkpoints so another operator can determine exactly how far the run advanced.
Pre-cutover migration rehearsal
1. Rehearse breaking or additive
Before sign-off, restate this article-specific claim in one sentence: Changing defaults or narrowing input is breaking; adding output can still break exhaustive clients. Build a controlled exercise that includes old SDKs and recorded consumer contracts. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where the specification omits a behavior clients actually use. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve deserialization, fallback, and unknown-enum errors with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
2. Rehearse inventory consumers and behavior
Before sign-off, restate this article-specific claim in one sentence: Identify who calls which route and which undocumented assumptions matter. Build a controlled exercise that includes synthetic known clients against the inventory pipeline. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where traffic has no client identity or retention is shorter than a business cycle. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve unknown callers, last-seen distribution, and route/version use with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
3. Rehearse choose one negotiation surface
Before sign-off, restate this article-specific claim in one sentence: Paths are visible; media types preserve URLs but complicate caches. Build a controlled exercise that includes CDN behavior for every supported representation. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where header, path, and query versions combine into untestable variants. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve requests, cache hits, and missing-version defaults with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
4. Rehearse version adapters around one capability
Before sign-off, restate this article-specific claim in one sentence: Transport versions need not duplicate the order engine. Build a controlled exercise that includes shared domain cases plus boundary-specific fixtures. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where version checks spread through policy code and fixes diverge. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve adapter failures and normalized outcome differences with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
5. Rehearse parallel operation and canary
Before sign-off, restate this article-specific claim in one sentence: Two versions double selected tests, capacity paths, and support obligations. Build a controlled exercise that includes rolling versions, failover, and both dependency paths. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where V2 writes data V1 cannot read. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve SLOs and business outcomes split by version/client with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
6. Rehearse sunset v1
Before sign-off, restate this article-specific claim in one sentence: An announcement does not migrate a caller. Build a controlled exercise that includes cutoff in non-production and a controlled exception path. Record the expected durable state, response, and operator action before running it. During the exercise, deliberately introduce the condition where old clients silently route into incompatible semantics or emergency rollback code is gone. The team must explain whether to retry, reject, compensate, roll back, or wait. Preserve deprecated calls by owner, blockers, post-sunset traffic, and exceptions with enough dimensions to compare the expected and observed path. Finish by assigning ownership and documenting the threshold that would force the design to be reconsidered.
Conclusion: version the incompatible boundary
Additive change still needs tolerant clients and contract tests. Truly incompatible behavior needs explicit negotiation, adapters, parallel operation, migration support, and an enforceable sunset. A version number earns its cost only when it names a coherent contract that clients, support staff, telemetry, and incident responders can identify. The durable lesson is to state guarantees in language clients and operators can verify, then build the smallest mechanism that satisfies them under retries, concurrency, deployment, and partial failure. Revisit the decision when traffic, risk, or ownership changes.
For the resource-contract foundation behind this migration, study REST API Design: Resource Contracts That Clients Can Trust. Implementation checklists and planning aids are available in the Prime Axiom resource library.
Authoritative references
The specifications define negotiation and sunset signals, but consumer telemetry determines whether a particular retirement is safe.



