Skip to content

API Versioning & Evolution — Detailed#

Compatibility kinds#

Backward compat Forward compat
Definition new server can read old client new client can read old server
Example optional field added client tolerates unknown fields
Required by always usually

Versioning strategies#

flowchart TB
  subgraph URI[URI versioning]
    A1["/v1/orders"]
    A2["/v2/orders"]
  end
  subgraph Header[Header versioning]
    B1["Accept: application/vnd.x.v2+json"]
  end
  subgraph Param[Query param]
    C1["?version=2"]
  end
  subgraph Evol[Evolution - no version]
    D1[Add fields only<br/>tolerate unknown<br/>never break]
  end

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class A1,A2,B1,C1,D1 service;
Strategy Pros Cons
URI /v1/... obvious, cache-friendly, easy mental model URL churn, multiple impls
Header Accept clean URLs, content-negotiated hard to test in browser, less visible
Query param trivial to test not idiomatic, cache-noisy
Evolutionary (no version) no breaking changes, single codebase slower change cadence

Most public APIs default to URI versioning; gRPC + Protobuf use evolution.

What's safe to change#

Change Safe?
Add new optional field yes
Add new endpoint yes
Add new enum value yes — clients must tolerate
Rename field breaking
Remove field breaking
Tighten validation breaking
Loosen validation safe
Change semantic of existing field breaking

Sunset window#

sequenceDiagram
  participant A as v1 clients
  participant Srv as Server
  participant B as v2 clients
  Note over Srv: v2 launched
  A->>Srv: /v1/...
  Srv-->>A: 200 + Sunset: Wed, 30 Jun 2027 + Deprecation: true
  Note over A: client devs migrate
  B->>Srv: /v2/...
  Srv-->>B: 200
  Note over A,Srv: 12 months later
  A->>Srv: /v1/...
  Srv-->>A: 410 Gone
  • Announce deprecation; emit Deprecation: true + Sunset: headers (RFC 8594).
  • 6–12 month window typical for paid customers; 3 months for SDK-owned clients.

gRPC + Protobuf rules#

  • Don't reuse field numbers.
  • Don't change field types.
  • New fields → next free tag, with defaults.
  • Removed fields → reserve the tag number forever.
  • Reorganise messages only inside the same package version.

REST: error contract#

  • Use a structured error envelope (Problem Details RFC 7807):
    { "type": "https://errs/insufficient_funds",
      "title": "Insufficient funds",
      "status": 422,
      "code": "INSUFFICIENT_FUNDS",
      "trace_id": "abc-123" }
    
  • Stable codes + stable types — adding new codes is OK if old clients already handle "unknown".

Pagination, IDs, filters#

  • Pagination: cursor-based, opaque. Stable across additions.
  • IDs: prefix to identify type (ord_abc123) — easy to grep, hard to confuse.
  • Filters: support a stable subset; new filters add to the spec, never re-purpose.

Anti-patterns#

  • "v2 means v1 is dead today" — clients can't react that fast.
  • Breaking semantics in a "patch" — never.
  • Multiple versions with shared mutable state — fix bugs in one and not the other.
  • Header version negotiation behind a CDN that strips headers.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD CDN edge caching for static assets cdn
HLD CRDTs commutative replicated data types crdts
HLD API versioning & evolution URI / header versioning, sunsetting api-versioning-evolution
LLD REST API design verbs, statuses, pagination, errors rest-api-design
LLD Behavioural patterns Strategy, Observer, State, Command, Chain behavioral-patterns