API Versioning

API versioning lets you evolve your API while existing clients keep working. The goal isn't to version often — it's to version rarely, by making most changes additively, and to have a clean, well-communicated path when a breaking change is truly unavoidable.

The mental model that saves the most pain: a version bump is a cost you impose on every client, so earn it. Add before you change, and change before you break.

TL;DR

Quick Example

URL path versioning — old clients keep hitting v1 while v2 ships breaking changes:

Core Concepts

Breaking vs non-breaking

Design clients to be tolerant readers (ignore unknown fields) so additive changes never break them.

Version lifecycle

  1. Active — fully supported.
  2. Deprecated — sunset date announced; still works.
  3. Retired — removed.

Versioning Strategies

URL versioning is the pragmatic default for most public APIs.

Best Practices

Version sparingly and clearly

Start at v1 (never v0), bump the major version only for breaking changes, and keep at most 2–3 active versions with migration guides.

Run a real deprecation process

  1. Announce the deprecation and a sunset date.
  2. Add a Deprecation (and Sunset) response header.
  3. Log usage of deprecated endpoints.
  4. Reach out to high-volume clients directly.
  5. Retire only after the sunset date.

Common Mistakes

Versioning for additive changes

Breaking a version in place

FAQ

When should I create a new API version?

Only for a breaking change you can't avoid — removing/renaming fields, changing types, or altering auth. Additive changes (new optional fields, new endpoints) should ship into the current version without a bump.

Which versioning strategy is best?

URL path versioning (/v2/...) for most APIs: it's explicit, easy to route, and easy to test. Header/media-type versioning keeps URLs clean but is harder to discover and debug. Query-param versioning is simplest but the least clean.

How many versions should I support at once?

Two or three active versions during a transition. More than that multiplies testing and support cost. Use a clear deprecation timeline to retire old versions.

How do I avoid versioning altogether?

Make changes additive and design tolerant clients that ignore unknown fields. GraphQL takes this further — clients request only the fields they need, so the schema can evolve without versioned endpoints. See GraphQL.

Related Topics

References