REST API
Beginner
1 min read
Backward-Compatible API Evolution
Example
# ----- Design choices that enable non-breaking evolution -----
# BAD: bare array — can't add metadata later without breaking
GET /products
[{ "id": 1 }, { "id": 2 }]
# GOOD: envelope — can add meta/links without breaking clients
GET /products
{ "data": [{ "id": 1 }, { "id": 2 }], "meta": { "total": 2 } }
# BAD: boolean flag that gets overloaded
{ "active": true } # later "active" needs to mean 3 states — now a breaking change
# GOOD: use enums from the start
{ "status": "ACTIVE" } # can add "SUSPENDED", "PENDING" without breaking old clients
# BAD: flat structure is hard to extend
{ "user_first_name": "Alice", "user_last_name": "Smith" }
# GOOD: nested object — add fields to the object without top-level pollution
{ "user": { "firstName": "Alice", "lastName": "Smith" } }
# Additive changes that are non-breaking:
# - Add new optional request fields
# - Add new response fields (clients MUST ignore unknown fields)
# - Add new enum values (clients MUST handle unknown enums gracefully)
# - Add new endpoints
# - Add new optional query parameters
# Contract testing with Pact ensures both sides honour the contract:
# npm install @pact-foundation/pact
# Generates: pacts/consumer-provider.json verified on CI