Skip to main content
Adopt

IPA-118: Extensible by Default

Signaling to clients any intentions for future extensibility and designing APIs conservatively reduces the potential of unintended impact.

Guidance

  1. API specs must not set additionalProperties to false, so that additional fields can be added later without breaking existing clients.

    components:
    schemas:
    User:
    type: object
    properties:
    id:
    type: string
    name:
    type: string
    Why:

    Leaving additionalProperties unset (it defaults to true) lets a future field appear in responses without invalidating the schema a client already validates against.

    components:
    schemas:
    User:
    type: object
    additionalProperties: false
    properties:
    id:
    type: string
    name:
    type: string
    Why:

    additionalProperties: false rejects any field not listed today, so adding a new field becomes a breaking change for clients that validate responses strictly.

  2. Request parameter data constraints should be specific and restrictive, so that the accepted range can be widened later without breaking existing clients.

    parameters:
    - name: status
    in: query
    schema:
    type: string
    enum: [ACTIVE, ARCHIVED]
    Why:

    A narrow enum can later gain a value without affecting clients that send only the existing ones. Widening an accepted set is backward compatible; narrowing it is not.

    parameters:
    - name: status
    in: query
    schema:
    type: string
    Why:

    An unconstrained string accepts any value from day one, leaving no room to add meaning to new values later and no way to tighten the contract without breaking callers that already send arbitrary input.

    1. Enumerate every parameter under paths.*.*.parameters and every shared parameter under components.parameters.

    2. For each parameter, inspect its schema for constraints appropriate to the type: enum for closed value sets, minimum/maximum for numbers, minLength/maxLength/pattern for strings, format where one applies.

    3. Flag any parameter whose value space is broader than the values it actually accepts — a bare string or integer with no constraint where the description or behavior implies a bounded set.

    4. Report each under-constrained parameter, since a constraint can be relaxed later without breaking clients but cannot be tightened.

  3. API producers should default to multi-cloud support when implementing features.

    paths:
    /deployments:
    post:
    operationId: createDeployment
    requestBody:
    content:
    application/json:
    schema:
    type: object
    properties:
    provider:
    type: string
    enum: [PROVIDER_A, PROVIDER_B, PROVIDER_C]
    region:
    type: string
    Why:

    The request lets the caller pick from every supported provider, so the feature works across providers rather than assuming a single one.

    paths:
    /deployments:
    post:
    operationId: createDeployment
    requestBody:
    content:
    application/json:
    schema:
    type: object
    properties:
    region:
    type: string
    Why:

    With no provider field, the feature implicitly hard-codes one provider. Adding multi-provider support afterward forces a new field onto an already-shipped contract.

    1. Identify the operations and request/response schemas that introduce the feature under review.

    2. Determine whether the feature is cloud-provider dependent by inspecting the schema for provider, region, or location fields and, where the spec is ambiguous, the backing source code or service configuration.

    3. For a provider-dependent feature, confirm the contract admits more than one provider — for example a provider enum listing each supported provider rather than a single hard-coded value.

    4. Report any feature whose contract or implementation assumes a single cloud provider where multi-cloud support is feasible.

Further reading