API contract evolution
Change an API without stranding its existing clients
Compatibility includes behaviour, defaults and error handling as well as field names. Review what older callers rely on before changing the contract.
In this article
A valid response can still break a client
An order API adds pagination to an endpoint that previously returned every matching order. The response remains valid JSON and includes the same item fields, but an older client reads only the first page and assumes its list is complete.
The schema did not reveal the whole contract. Callers also depend on default behaviour, ordering, field meaning and error states. A change can remain syntactically valid while causing a client to make the wrong business decision.
Start with the supported caller population. An internal client deployed with the server has different migration constraints from a mobile application or external integration that updates on its own schedule.
Distinguish additive shape from compatible behaviour
Adding an optional response field is often easier to introduce than removing or renaming one, but it is not automatically harmless. Strict parsers, exhaustive enum handling and generated clients can respond differently to new values.
For request fields, preserve the old behaviour when the new field is omitted unless a deliberate versioned change says otherwise. Making the field optional in the schema while changing its default can still alter old callers' results.
Keep value semantics stable. A field called amount should not change from minor units to decimal major units merely because both representations fit a numeric type. Introduce an explicit new representation and migration rule.
Use a transition contract
When a change cannot preserve the old meaning, provide a clear version or compatibility path. Define how both contracts map to the underlying business operation and what happens if a caller supplies conflicting old and new fields.
- Existing clientContinues using its documented request and response
- Contract adapterValidates and translates the selected version
- Business operationApplies current rules and authority checks
- Versioned responseReturns the shape and semantics promised to that caller
The diagram is a simplified request path. New clients use the corresponding new adapter. Avoid duplicating the entire business implementation merely to support two wire formats, while preserving genuinely different semantics where required.
Test old callers against the new server
Keep representative client or contract fixtures, including errors, omitted fields and unknown enum values. A happy-path schema diff catches only part of the risk.
Test the actual client behaviour where possible. A response can satisfy a formal schema while triggering a brittle assumption in a supported SDK or integration. Use observed callers to prioritise compatibility work without treating every accidental undocumented behaviour as an unlimited promise.
Retire with evidence
Measure remaining use of the old contract and identify its owners. A deprecation date needs a communication and migration process, not just a comment in the specification.
Keep rollback compatible with data written by new clients during the transition. A server restoration that cannot interpret new records may not be a usable recovery path.
The release is ready when existing supported callers continue to behave correctly or have a concrete migration route, and the team can explain which compatibility promise the new version makes.
Primary sources
Google AIP-180: backwards compatibilityGoogle AIP-185: API versioningReferences checked 11 September 2026.