Paradise CodeSoftware Studio
Back to articles
Backend EngineeringUpdated 12 min read

API Versioning and Backward Compatibility: Contracts That Do Not Break Clients

URL/header versioning strategies, safe schema changes, and deprecation policy for public and internal product APIs.

APIversioningcompatibilityRESTcontracts

Ali Mortazavi

Founder, Paradise Code

Compatibility is a product feature, not a tech detail

Every removed field or changed meaning breaks someone you cannot see: an old mobile app, a customer script, a partner integration. Versioning is a time-bound promise about change. Without that promise, feature speed trades away trust in the API.

First decide whether the API is public or internal. Internal APIs still need versions, but deprecation cycles can be shorter.

Where the version lives: path, header, or media type

Path versions (`/v1/...`) are explicit and easy for gateways and logs. Headers look cleaner in URIs but complicate discovery and caching. For most B2B and mobile products, path versioning is the clearest contract.

Reserve major versions for true breaks. Additive changes should not mint v2, or you get version explosion instead of discipline.

Safe changes vs breaking changes

Safe usually means: new optional fields, new endpoints, new enums that unknown clients ignore. Breaking means: removing fields, changing types, changing default meaning, making a formerly optional field required.

For renames, run a dual period: old and new fields together, then deprecation warnings, then removal in a major version.

Testable contracts and consumer-driven checks

Validate OpenAPI/Protobuf contracts in CI. Compatibility tests before merge prevent silent breaks. For multi-client teams, consumer-driven contracts pay off early.

Keep real response examples in docs—not only schemas. Clients copy examples; stale examples become distributed bugs.

Deprecation policy with dates and metrics

Deprecation without a date and without traffic metrics on the old version is theater. Announce a sunset date, monitor usage, and talk to client owners.

For mobile, accept store reality: users do not update. Sometimes you must keep an old version longer or feature-flag capability server-side.

Internal service and event versions

The same principles apply to messages and gRPC: do not delete fields, keep a compatibility mode, and tolerate unknown consumers.

An anti-corruption layer at boundaries lets internal models evolve without shaking the external contract.

Frequently asked questions

Does every UI change need a new API version?

No. Only contract-breaking changes. New features usually add optional fields or endpoints.

How many versions should we keep alive?

As few as possible—usually N and N-1. More explodes test and security cost unless you have contractual commitments.

Does GraphQL remove the need for versioning?

No; it changes the shape. Field deprecation and tolerance for old clients remain necessary.

Insights

Need these ideas implemented in your product?

Paradise Code supports you from consult to full delivery.

Request collaboration