Deprecated endpoints marked only in code comments — "legacy, use the new path" — are invisible to consumers reading the API schema or watching response headers. Tooling that scans for deprecated fields (OpenAPI linters, SDK generators, custom contract tests) cannot find what is not formally marked. iso-25010:2011 compatibility.interoperability is the direct casualty: consumers have no automated way to discover they are using a path scheduled for removal, and the migration window effectively starts the day removal happens rather than the day deprecation was intended.
Medium because unmarked deprecations leave consumers unaware of scheduled removals until breakage occurs, removing the entire benefit of a deprecation period.
Mark deprecated elements formally in the schema and in response headers, not only in code comments:
# OpenAPI -- deprecated endpoint with removal date:
/api/users/search:
get:
deprecated: true
description: "Use GET /api/users?q= instead. Will be removed 2026-07-01."
# GraphQL -- deprecated field:
type User {
fullName: String
name: String @deprecated(reason: "Use fullName instead")
}
For REST, also add HTTP headers on every response from deprecated endpoints: Deprecation: true and Sunset: Sat, 01 Jul 2026 00:00:00 GMT. Tooling like spectral can enforce that all deprecated schema elements include a reason and a sunset date.
ID: api-design.versioning-evolution.deprecation-markers
Severity: medium
What to look for: Check whether deprecated API elements are properly marked. For REST: look for Sunset or Deprecation HTTP headers, deprecated fields in OpenAPI spec (deprecated: true), or deprecation notices in documentation. For GraphQL: look for @deprecated(reason: "...") directives on fields, arguments, or enum values. For gRPC: look for [deprecated = true] field options in .proto files. Also check: if deprecated elements exist, is there a removal timeline?
Pass criteria: Count all elements marked or referenced as deprecated, legacy, or old across the codebase. Either (a) no deprecated elements exist (everything is current), or (b) 100% of deprecated elements are marked in the schema/spec AND include a reason and/or migration path. Deprecated REST endpoints return a Sunset or Deprecation header.
Fail criteria: Deprecated elements exist (documented in changelog or comments as "old" or "legacy") but are not marked as deprecated in the schema, spec, or response headers. Or elements have been marked deprecated with no migration guidance.
Skip (N/A) when: The API is at version 1.0 with no prior versions and no deprecated elements. Signal: single version exists, no "legacy" or "deprecated" comments in code.
Detail on fail: Identify unmarked deprecated elements (e.g., "Code comments mark /api/users/search as 'legacy, use /api/users?q= instead' but the endpoint is not deprecated in the OpenAPI spec and returns no Deprecation header."). Max 500 chars.
Remediation: Mark deprecated elements properly so tooling and consumers can discover them:
# OpenAPI -- deprecated endpoint:
/api/users/search:
get:
deprecated: true
description: "Use GET /api/users?q= instead. Will be removed 2026-07-01."
# GraphQL -- deprecated field:
type User {
fullName: String
name: String @deprecated(reason: "Use fullName instead")
}
For REST, also add HTTP headers: Deprecation: true and Sunset: Sat, 01 Jul 2026 00:00:00 GMT.