API Design for Large Teams
Coordinate API changes across producer and consumer teams with one contract source, compatibility evidence, security controls, release gates, and owned recovery.
trigger="Several teams depend on an API, or a proposed change may affect independently deployed consumers." owner="The API product or service owner accountable for its contract and consumer support." participants={["Provider team", "Named consumer maintainers", "Platform lead", "Security reviewer", "Developer-experience owner", "Operations lead"]} prerequisites={[ "A current API and consumer inventory, including deployed versions and contact owners.", "A version-controlled contract, representative requests, and documented behavioral expectations.", "A test environment and a release process that can stop or reverse an incompatible change." ]} outputs={[ "A reviewed API change record with ownership and consumer impact.", "Provider, consumer, security, and operational verification evidence.", "A coordinated deployment and migration plan with explicit rollback limits." ]} doneWhen={[ "Known affected consumers verify the proposed behavior and deployment order.", "The published contract, documentation, examples, and implementation agree.", "Security and cache isolation tests pass through the actual deployment path.", "On-call teams can identify affected consumers and execute the agreed recovery." ]} />
Coordinate a promise across teams
An API is a shared dependency, not merely the provider team's code. Consumers may use different libraries, release schedules, and assumptions. A locally passing change can still break a generated client or alter a workflow without changing the response schema.
Use this playbook to organize ownership, evidence, and release decisions. The companion API Design and Versioning Guide covers representation and migration details. Keeping those responsibilities distinct avoids turning every API review into a complete redesign.
There is no team-count threshold at which governance suddenly becomes necessary. Use the lightest process that makes consumer impact visible and keeps production changes accountable.
1. Inventory contracts and actual consumers
The API owner records the purpose, lifecycle state, authoritative contract location, current implementations, and support path for each interface. Consumer maintainers identify the operations, fields, ordering, errors, and timing behavior on which their workflows depend.
Use deployment records and sanitized telemetry to find consumers, but do not treat an absence of recent traffic as proof that an integration is unused. Scheduled jobs, disaster-recovery clients, and seasonal workflows can be quiet for long periods. Public APIs may have consumers the provider cannot enumerate; their compatibility policy must account for that uncertainty.
| Responsibility | Accountable role | Evidence | | --- | --- | --- | | Business semantics and supported behavior | API owner | Contract and lifecycle policy | | Implementation conformance | Provider lead | Tests against the built service | | Consumer expectations and migration | Consumer maintainer | Versioned contract or integration tests | | Authentication, authorization, and data handling | Security owner | Threat and negative-test results | | Documentation and onboarding | Developer-experience owner | Tested examples and support route | | Deployment and incident response | Operations lead | Version inventory and runbook |
Avoid creating a review board that owns every decision but operates none of the services. Escalate disputed cross-team tradeoffs to a named decision-maker, and keep routine conforming changes within the provider's workflow.
2. Choose one contract-authoring workflow
For new cross-team APIs, design-first can let consumers review the contract before implementation. For an existing code-first service, a generated contract can be practical. Neither approach eliminates the need to verify behavior. Choose the authoritative source and record how generated outputs are refreshed.
The OpenAPI Specification describes an interface format; it does not mandate design-first or code-first development. Pin the OpenAPI version supported by the chosen validators, generators, and documentation tools. A newer specification version is not useful if the team's tools interpret it inconsistently.
| Workflow | Authoritative source | Required drift check | | --- | --- | --- | | Design-first | Reviewed interface definition | Built provider matches the definition and behavioral tests | | Code-first | Reviewed implementation and annotations | Generated definition is reproducible, diffed, and consumer-reviewed | | Transitional | Explicitly named temporary source | Reconciliation owner and a date or condition for ending dual maintenance |
Do not hand-edit a generated file while continuing to present the generator as authoritative. Keep the contract, generated documentation, SDK version, and implementation commit traceable to the same release.
"type": "svg-architecture", "title": "One contract, several dependent artifacts", "nodes": [ ], "links": [ ], "caption": "The contract source can be design-first or code-first. Every dependent artifact needs release-level traceability and verification." }} />
3. Review compatibility beyond the schema diff
The provider lead classifies a change and identifies affected consumers before implementation. A schema diff is a useful filter, not the complete decision. Review field meaning, defaults, authorization, rate limits, latency, error codes, pagination, and side effects.
Adding a field is not unconditionally safe. Strict deserializers can reject unknown properties; generated clients may assume a closed enum; newly returned data can affect signatures, equality checks, or downstream validation. Google's compatibility guidance highlights several change constraints, including caution around response enum values.
| Proposed change | Evidence required | | --- | --- | | Add an optional response field | Supported clients ignore or handle it; sensitive data is not newly exposed | | Add a response enum value | Consumers have tested unknown-value behavior | | Add an optional request field | Omission preserves existing behavior and validation | | Change sorting or pagination | Consumers still process the expected records without unsafe assumptions | | Change error or retry behavior | Clients do not misclassify failures or duplicate effects | | Tighten access or quotas | Security need, migration impact, and operational response are explicitly reviewed |
When a change is incompatible, prefer an additive transition or a separately supported contract version. Emergency security corrections may require a different response, but they still need an owner, consumer communication, and a record of the risk accepted.
4. Use tests that match the release question
Run provider conformance tests against the built service. Run consumer-driven contracts or representative integration tests for behavior consumers depend on. Include negative tests and stateful workflows rather than checking only a successful response shape.
Consumer-driven contracts do not prove every business rule or security property. They verify declared expectations. Undeclared consumers and untested error paths remain gaps that the release record must expose.
If using Pact, its can-I-deploy documentation depends on versioned verification results and accurate environment deployment records. Checking “latest” artifacts is not equivalent to checking the versions actually deployed together. Record deployment success only after the release is confirmed.
Gate the release on relevant evidence:
- Provider behavior matches the contract and published examples.
- Affected consumer versions pass their expected interactions.
- Object-level and field-level authorization fail safely.
- Pagination, retries, cancellation, and long-running operations behave as documented.
- Rate and concurrency controls protect shared dependencies.
- The old and new versions can coexist during the rollout window.
A missing verification result is not a pass. Define whether it blocks deployment or requires an explicitly approved exception, and name who owns that exception.
5. Make shared conventions operational
Keep a concise style guide for naming, errors, pagination, dates, identifiers, partial success, idempotency, and lifecycle metadata. Allow documented exceptions when a protocol or business operation requires them. Resource-oriented HTTP, GraphQL, and RPC interfaces have different capabilities and client requirements; no protocol is universally fastest or simplest.
Use the Problem Details standard when a standard HTTP error representation fits. Provide stable machine-readable meaning, safe explanations, and a correlation identifier. Do not expose stack traces, credentials, or customer values merely to make an error more descriptive.
Define limits by the cost and risk of the operation. A request-rate limit alone may not bound long-running work or expensive queries. Specify concurrent work, payload size, batch behavior, deadlines, and queue policy where relevant. Document throttling responses and retry guidance without implying that every failure is safe to retry.
Keep authentication separate from authorization. The resource-owning service must enforce the applicable tenant, object, field, and action policy or use an equivalently enforced reviewed control. Successful gateway authentication does not establish permission for every downstream resource.
6. Review HTTP caching as a security decision
For sensitive personalized responses, use an appropriate Cache-Control: no-store policy. Where local reuse is acceptable, private with explicit freshness rules can prevent shared-cache storage. Neither directive replaces transport security, access checks, or controls over application-managed storage.
Vary: Authorization alone does not authorize shared-cache reuse of authenticated responses. RFC 9111 section 3.5 separately governs responses to requests containing Authorization. Deliberate shared caching needs a permitted response policy and a reviewed design, not a header copied from an example.
For any intentional edge cache, test tenant and user separation, relevant query and representation dimensions, permission revocation, logout, error responses, and stale behavior. Verify the actual CDN configuration, including overrides of origin headers. Avoid putting bearer secrets into diagnostic cache-key logs.
If isolation fails, disable the affected cache behavior, contain exposure, and follow incident response. A purge or corrected header stops some future reuse; it does not undo responses already disclosed.
7. Coordinate deployment and recovery
"type": "flow", "title": "A consumer-aware API release", "steps": [ ], "caption": "A failed gate holds the release or uses an approved exception. Deployment order depends on which versions can coexist safely." }} />
For an additive transition, deploy a compatible provider before consumers rely on new behavior. Keep the old behavior while supported consumers migrate. A consumer rollback may still need the newer provider, and a provider rollback may break a consumer already using new fields. Test the specific rollback pair.
| Failure | Immediate action | Follow-through | | --- | --- | --- | | Consumer contract fails | Stop rollout and identify the version pair | Repair or restore a supported pair | | Authentication or policy regression | Contain the affected route or capability | Review denied and allowed operations with security | | Changed defaults alter writes | Stop new affected operations | Reconcile records already changed | | Cache leaks a representation | Disable reuse and invoke incident response | Determine affected identities and invalidate safely | | New client causes retry amplification | Bound admission and retries | Correct client behavior before expansion |
Routing rollback does not reverse writes, emitted events, or external actions. Record a reconciliation procedure and the point beyond which forward recovery is safer than reverting code.
8. Maintain lifecycle and consumer communication
Agree notice periods from contracts, consumer release constraints, and risk, rather than a universal number of months. Deprecation is a communication stage, not permission to break an interface immediately. Keep migration instructions, examples, owners, and support routes available.
Use runtime lifecycle signals where supported, but do not depend on every client reading them. Contact registered maintainers, observe adoption, and investigate quiet integrations. Retirement needs evidence that obligations are satisfied and affected consumers have a valid outcome.
For version-selection and retirement mechanics, use API Design and Versioning. For traffic-layer responsibilities, use API Gateway vs Service Mesh.
9. Run a cross-team change rehearsal
Choose one proposed change that affects at least two consumers and rehearse the complete decision before implementation. The provider presents the intended outcome, behavioral and schema differences, supported version pairs, security impact, rollout order and recovery limits. Consumer owners identify the assumptions their clients actually make, including generated-code behavior, local caching, retries and release constraints.
Use a compatibility worksheet with one row per supported consumer version. Record whether that version can run against the current provider, the proposed provider and the fallback provider. Link the exact verification result. Mark unknown combinations as unknown, not compatible. Include at least one consumer maintained outside the provider team's normal release cadence.
Ask each participant to answer five questions:
- What observable behavior changes even if the schema is additive?
- Which identity and resource authorization decisions occur on the path?
- Can either side roll back independently after the first new write or external effect?
- How will an operator identify the deployed provider and consumer versions?
- Who decides when the old behavior may be retired?
Then simulate a failure after a bounded cohort has used the new behavior. The operator should stop expansion, identify affected version pairs, preserve request and correlation evidence, and select a compatible recovery path. If already-committed writes differ under the new behavior, the data owner must explain reconciliation or forward recovery. A load balancer switch alone is not a recovery plan.
Retain the rehearsal output with the API change record. If the exercise reveals an unregistered consumer, ambiguous ownership, or an unsupported version pair, revise the rollout before construction is complete. Finding the gap early is the purpose of the rehearsal.
10. Define the evidence required to call the change complete
Completion has three stages. Provider ready means the implementation, contract, examples and operational controls match the proposed release. Consumer compatible means supported consumer versions have current evidence for the behaviors they depend on. Migration complete means the agreed consumers run a supported version and the old behavior can be retired without violating an obligation.
For provider readiness, test happy and negative paths, authorization at the object and field level, deadlines, pagination boundaries, idempotency, rate and concurrency behavior, observability, and sensitive-data handling. Confirm that the built artifact corresponds to the reviewed contract. A source-branch test does not validate a different deployed binary.
For consumer compatibility, combine contract verification with one representative workflow where the risk justifies it. Confirm parsing of unknown response fields and enum values, treatment of new errors, retry safety, timeout behavior and cache semantics. Consumers that transform or persist the response need data-compatibility evidence as well.
For migration completion, use deployed-version evidence and owner acknowledgement. Quiet traffic does not prove a consumer is retired. A periodic or disaster-recovery integration may be inactive during the observation window. Check registered ownership, credentials, scheduled work, contractual users and documented dependencies before disabling the path.
Publish the final decision with remaining coverage gaps. If an exception permitted release without a consumer result, assign an expiry, compensating control and closure owner. Do not let a temporary exception silently become the permanent support policy.
Keep the consumer inventory alive
Update registration when credentials, subscriptions, gateway routes or SDK packages are created, not only during an annual survey. Record the accountable team, business use, environment, protocol, current version, data classification, operational contact and expected retirement route. Where runtime discovery is available, compare observed identities and traffic with the declared inventory while respecting privacy and retention limits.
Investigate differences instead of deleting quiet entries automatically. An unobserved consumer may be dormant, seasonal, misconfigured, routed through an intermediary, or used only during recovery. An observed but unregistered consumer needs an owner and support decision. If ownership cannot be established, restrict expansion and escalate the risk before an incompatible change.
Review the inventory at deprecation and incident time. It should help the team locate affected owners and understand which version pairs require evidence. A catalog entry without a current contact or deployed-version signal is a clue, not proof of compatibility.
Revalidate it whenever routing, ownership, or authentication boundaries change materially.
API change record
API / accountable owner / contract source:
Change intent and consumer benefit:
Changed schema and changed behavior:
Affected consumers and deployed versions:
Compatibility evidence and known coverage gaps:
Authorization / caching / data handling impact:
Provider and consumer deployment order:
Stop conditions and incident owner:
Safe rollback version pairs:
Committed-effect reconciliation:
Documentation, SDK, and example versions:
Migration communication and retirement decision:Completion checklist
"The API has a named owner, a consumer inventory, and one authoritative contract workflow.", "Additive changes have been tested against supported clients and relevant behavioral assumptions.", "Verification results correspond to the versions that will run together.", "Published examples, SDKs, implementation, and documentation are traceable to the release.", "Authorization and cache-isolation tests pass through the deployed request path.", "Rollout and rollback compatibility are explicit, including committed effects.", "Consumer communication and lifecycle decisions have accountable owners." ]} />
Ampity's backend systems and APIs service is the related service for implementing the contract and delivery controls. Acceptance should be based on consumer compatibility and operating evidence, not an unsupported onboarding-time or support-ticket promise.