API & BACKEND ARCHITECTURE / SYSTEM CONCEPT BRIEF

API versioning

API versioning is how you change an API without breaking existing clients.

IntermediatePhase 02 / Topic 16 of 20RequirementsTrade-offsFailure modes
01

Overview

API versioning is how you change an API without breaking existing clients. Once mobile apps, partners, and other teams depend on an API, removing a field or changing its meaning can break them. Versioning gives clients a stable contract while the API evolves.

Common strategies are a version in the URL path (/v1/orders), a header (Accept or a custom API-Version), a query parameter, and date-based versions (Stripe's 2024-06-20). Equally important is evolving without versions where possible, through additive, backward-compatible changes, and having a clear deprecation process when breaking changes are unavoidable.

Editions of a textbook

A new edition can reorganize chapters, but students in an existing course keep using the edition their syllabus references. Publishers announce when old editions will stop being printed.

02

When to use it

  • Public or partner APIs with clients you do not control.
  • Mobile backends where old app versions stay installed for years.
  • Making breaking changes to response shapes or semantics.
  • Designing an API governance policy.
03

Where it shows up in interviews

Evolving public APIs

Recognize it when: change an API used by external clients.

  • Design a public payments API
  • Design a mobile backend with old app versions
Contract governance

Recognize it when: many teams consume internal APIs.

  • Design an API platform for microservices
04

Where it is used in real software

Stripe

Uses date-based versions pinned per account, with a header override, and maintains old versions for years.

GitHub and Twilio

GitHub uses a header-based API version; many APIs, including Twilio's, use versions in URL paths.

Google APIs

Follow AIP guidance with major versions in the path (v1, v2) and backward-compatible minor changes.

05

Key terms

Breaking change
Change that can make existing clients fail (removing or renaming fields, changing types or meaning).
Backward compatible
Old clients keep working (adding optional fields, new endpoints).
Deprecation
Announcing a version or field will be removed, with a timeline.
Sunset header
HTTP header indicating when a resource will stop being available.
Tolerant reader
Clients ignore unknown fields so additions do not break them.
06

How it works, step by step

  1. 1
    Prefer additive changes

    Add fields and endpoints instead of changing existing ones.

  2. 2
    Choose a versioning scheme

    Path, header, or date-based; apply it consistently.

  3. 3
    Introduce a new version only for breaking changes

    Keep the old version running in parallel.

  4. 4
    Translate between versions

    Map old requests and responses to the new internal model at the edge.

  5. 5
    Deprecate with a timeline

    Announce, add Deprecation and Sunset headers, measure usage, then remove.

07

Versioning strategies

Trade-offs

Step 1 / 4
StrategyExampleProsCons
URL path/v2/ordersVisible, easy to route and cacheURLs change; coarse-grained
HeaderAPI-Version: 2Clean URLs, per-request controlLess visible; harder to test in a browser
Query parameter/orders?version=2Easy to tryEasy to forget; caching quirks
Date-based2024-06-20Fine-grained evolution per accountRequires version translation layers

NOWStrategy: URL path | Example: /v2/orders | Pros: Visible, easy to route and cache | Cons: URLs change; coarse-grained

Path versioning is the most common default; date-based versioning suits APIs with frequent evolution and long-lived integrations.

08

Implementation

// Internal model evolves; adapters keep old contracts stabletype OrderV2 = { id: string; total: { amount: number; currency: string }; status: "pending" | "paid" }; const toV1 = (o: OrderV2) => ({ id: o.id, total_cents: o.total.amount, status: o.status });   // old shape app.get("/v1/orders/:id", async (req, res) => {  const order = await orders.get(req.params.id);  res.set({ Deprecation: "true", Sunset: "Wed, 31 Dec 2026 23:59:59 GMT", Link: '</v2/orders>; rel="successor-version"' });  res.json(toV1(order));}); app.get("/v2/orders/:id", async (req, res) => {  res.json(await orders.get(req.params.id));});
09

Complexity and performance

Versions maintainedKeep few (1-3)

Each version costs testing and maintenance.

Deprecation windowmonths to years

Mobile and partner integrations change slowly.

10

Trade-offs

Stability vs maintenance

Supporting many versions protects clients but multiplies code paths and tests; translation layers at the edge reduce the cost.

Granularity

Major path versions are simple but force big migrations; date-based or per-field evolution is smoother but more complex to implement.

11

Variants and related techniques

GraphQL evolution

GraphQL avoids versions by adding fields and deprecating old ones with @deprecated.

Consumer-driven contracts

Tools like Pact verify providers do not break consumers.

12

Common mistakes

  • Changing field meaning without a version.

    Fix: Semantic changes are breaking changes even if the type is the same.

  • Removing versions without measuring usage.

    Fix: Track traffic per version and contact remaining clients before sunset.

  • Clients that fail on unknown fields.

    Fix: Encourage tolerant readers so additive changes stay safe.

13

Interview questions

How would you version a public REST API?

Evolve additively whenever possible, use a clear scheme (often /v1 in the path, or date-based versions for fine-grained evolution), keep old versions running with translation adapters, and deprecate with announced timelines, Deprecation and Sunset headers, and usage monitoring.

What counts as a breaking change?

Removing or renaming fields or endpoints, changing types or formats, making optional fields required, changing default behavior or error codes, and changing the meaning of existing values.

14

Practice problems

ProblemDifficultyWhat it trains
Classify 10 API changes as breaking or notEasyCompatibility.
Design a deprecation plan for v1 to v2MediumMigration and communication.