An API deprecation and sunset policy should tell consumers two different things: when an interface became discouraged, and when it is expected to stop responding. Treating those dates as interchangeable creates a migration plan that looks precise but gives clients no reliable operating boundary.

HTTP now has standard signals for both stages. The Deprecation response header defined in RFC 9745 communicates a deprecation date. The Sunset header defined in RFC 8594 communicates when a resource is expected to become unresponsive. Neither header performs the retirement for you. The hard work is still inventory, notification, migration evidence and a controlled shutdown.

Deprecation is a warning; sunset is an availability boundary

A deprecation notice says that a resource is discouraged and may be removed in the future. Its date can be in the past, present or future. A future date gives clients advance notice that the deprecation state will begin later.

A sunset notice has a narrower operational meaning. It carries an HTTP date that indicates when the resource is likely to become unresponsive. RFC 8594 describes that date as a hint, not a promise of availability until the last second. A client still needs to handle earlier failure and ordinary service incidents.

The ordering rule is simple: a sunset date should not precede the deprecation date.

Signal What it communicates What it does not guarantee
Deprecation The resource is or will become deprecated at a stated date That traffic stops, the contract changes, or a replacement exists
Sunset The resource is expected to become unresponsive after a stated HTTP date Continuous availability until that date
Link: rel="deprecation" A place to read migration or policy information That clients will automatically follow the link
Link: rel="sunset" Information about the sunset policy or affected scope That every endpoint has the same shutdown date

A useful policy keeps these meanings separate in dashboards, runbooks and customer messages. “Deprecated” is a lifecycle state. “Sunset” is a scheduled service boundary.

Put machine-readable signals on the affected responses

RFC 9745 defines Deprecation as a Structured Field Date. A response can pair it with a link to human-readable guidance:

HTTP/1.1 200 OK
Deprecation: @1798761600
Link: <https://api.example.com/migrations/orders-v1>; rel="deprecation"

RFC 8594 defines Sunset with an HTTP-date:

HTTP/1.1 200 OK
Sunset: Thu, 30 Sep 2027 23:59:59 GMT
Link: <https://api.example.com/policies/sunsets/orders-v1>; rel="sunset"

The examples above are illustrative. The dates should come from the same approved retirement record that feeds documentation, status pages and account communications. Do not type them separately into several systems and hope they stay aligned.

Headers should appear on the responses that consumers actually receive. If a gateway injects them, verify that it scopes the rule to the intended version, hostname and operation set. A global rule applied to unrelated endpoints turns a precise signal into noise.

Define the retirement object before announcing it

“Version 1” is rarely precise enough. A retirement record should identify the service boundary in terms that engineering and consumers can test:

  • hostnames and base paths;
  • API version identifiers;
  • operations or event topics in scope;
  • authentication schemes and client types affected;
  • deprecation and sunset timestamps with time zone;
  • the replacement contract and migration guide;
  • named internal owner and decision authority;
  • known exceptions and their expiry dates.

For a shared resource, RFC 8594 allows the sunset link to describe a broader scope than one URL. That is useful, but the linked document must say what the scope is. Otherwise a client receiving the header on one endpoint cannot tell whether the date applies to the operation, the entire API version or a commercial plan.

If the replacement contract itself changes, review it separately. The OpenAPI breaking-change guide covers request and response compatibility; a sunset plan should not hide an unreviewed new contract behind a timeline.

Build the consumer inventory from evidence

A retirement plan needs more than a list of accounts that once created credentials. Use several sources and keep their limitations visible:

  1. Gateway or load-balancer logs show observed calls, but only for the retention window and routes that produced usable telemetry.
  2. Credential ownership identifies potential consumers, but a credential may be shared, rotated or abandoned.
  3. Distributed traces can connect old calls to internal services, but sampling may miss low-volume clients.
  4. Billing or entitlement records describe access rights, not actual traffic.
  5. Support and partner records can reveal off-platform workflows that logs do not explain.

Join these sources into a working inventory: consumer, owner, environment, last observed use, volume, affected operations, replacement readiness and contact state. Mark unknowns rather than filling them with assumptions.

Low traffic is not the same as no dependency. A month-end reconciliation job or quarterly compliance export may be business-critical and invisible during a short observation window. Set the observation period from the workload’s real cadence.

Give consumers a migration path they can test

A deprecation notice is useful only when it changes what a consumer can do next. The migration package should include:

  • the replacement endpoint or version;
  • an operation-level mapping from old to new;
  • authentication and scope changes;
  • examples for changed requests, responses and error handling;
  • a test environment or representative fixtures;
  • rate-limit and pagination differences;
  • a rollback or coexistence plan where supported;
  • the date after which the old interface is expected to stop responding.

For data-moving interfaces, call out state semantics as well as fields. A new pagination model can change how clients handle records inserted during a scan; the API pagination consistency guide explains that boundary. For callback migrations, document how signing and retry behaviour changes, using the webhook signature and replay guide where relevant.

Avoid saying “drop-in replacement” unless the client contract, operational limits and observed behaviour support that claim.

Stage the shutdown instead of discovering failures at the deadline

A practical sequence separates communication from enforcement:

1. Observe

Instrument the old surface and establish a consumer inventory. Add the response headers without changing behaviour. Verify that dates and links are correct in production responses.

2. Announce

Publish the migration guide and notify identified owners through approved channels. Record delivery attempts and responses, but do not treat a sent message as proof that a migration is complete.

3. Rehearse

Offer controlled test windows or account-level simulations when the service permits them. Measure which consumers still call the old interface and which failure modes appear.

4. Restrict

If policy and contracts allow, reduce access for confirmed migrated consumers or block new client registrations for the old version. Keep exception decisions time-bounded and owned.

5. Sunset

Apply the shutdown at the recorded scope and time. Monitor errors, support signals and rollback criteria. Keep the migration documentation available after retirement because delayed clients still need an explanation.

A blanket “brownout” is not automatically safe. Short failures can trigger retries, duplicate work or operational alarms. Design the rehearsal around the API’s side effects and the clients’ retry behaviour.

Use measurable exit criteria

A calendar date is necessary, but it is not enough to decide whether the system is ready. Add evidence-based checks:

  • no unidentified production consumer remains in the chosen observation window;
  • every exception has an owner and expiry;
  • the replacement meets agreed capacity and reliability requirements;
  • migration tests cover high-risk operations and side effects;
  • support, incident and rollback procedures are approved;
  • the public documentation, headers and internal change record agree on scope and dates.

Zero observed calls is one signal, not proof of zero dependency. State the retention window, sampling and excluded traffic whenever you use that metric.

Keep caches and intermediaries in mind

RFC 9745 notes that the deprecation header does not change the response semantics. RFC 8594 says the sunset header is not a caching directive. Neither should be used as a substitute for Cache-Control, contract versioning or error handling.

Gateways, SDKs and client libraries may also hide the response headers from application code. Test the signal at the consumer boundary, not only at the origin service. For important clients, give the lifecycle dates through both machine-readable responses and the migration channel they already use.

The policy record should survive the shutdown

Retirement evidence is useful after the endpoint is gone. Preserve the final scope, approved dates, consumer inventory summary, exceptions, migration material and the decision to disable. This gives support and incident teams a factual answer when an old integration reappears.

The record should also distinguish what was observed from what was inferred. “No calls in 90 days of complete gateway logs” is evidence with a window. “No one uses it” is a conclusion that may not survive review.

Review checklist

Before approving an API retirement, verify that:

  • the deprecation and sunset dates are distinct and ordered;
  • the affected resource scope is explicit;
  • Deprecation, Sunset and link relations are emitted where consumers can see them;
  • the linked migration material is public to the intended audience;
  • the consumer inventory combines traffic and ownership evidence;
  • low-frequency workflows are covered by the observation window;
  • the replacement contract and operational limits are tested;
  • exceptions have owners and expiry dates;
  • rehearsal failures cannot create unsafe side effects;
  • public, operational and machine-readable dates match.