Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a025c2-407a-7a32-b40a-f37a52f03f62
267 lines
11 KiB
Markdown
267 lines
11 KiB
Markdown
---
|
|
id: practice-pattern/interface-deprecation-strangler
|
|
title: InterfaceDeprecationStrangler
|
|
type: practice-pattern
|
|
scheme: practice-pattern/0.1
|
|
status: active
|
|
version: "0.1"
|
|
summary: Replace an interface gradually while metering legacy use, guiding callers, and gating removal on evidence.
|
|
aliases:
|
|
- Metered Interface Strangler
|
|
- Evidence-Gated Interface Deprecation
|
|
uses:
|
|
- model/governance
|
|
- model/observability
|
|
- model/devsecops
|
|
related_patterns: []
|
|
known_uses:
|
|
- state-hub-workstream-to-workplan-transition
|
|
---
|
|
|
|
# InterfaceDeprecationStrangler
|
|
|
|
## Intent
|
|
|
|
Phase out an old interface without guessing whether callers have migrated:
|
|
introduce and verify its successor, make deprecation visible to callers, meter
|
|
legacy use, progressively restrict the old behavior, and remove its final
|
|
tombstone only when evidence satisfies an explicit retirement policy.
|
|
|
|
## Context
|
|
|
|
Use this pattern when a service, library, event stream, command, file format, or
|
|
other integration surface must evolve while some callers may still depend on
|
|
the old interface. Caller inventory is incomplete, release cycles are not
|
|
coordinated, or removal has enough operational risk that absence of complaints
|
|
is insufficient evidence.
|
|
|
|
The old and new interfaces may coexist briefly, or the old interface may
|
|
already reject requests while still receiving attempts.
|
|
|
|
## Problem
|
|
|
|
An interface cannot safely remain forever, but deleting it on a planned date
|
|
can break unknown callers. Keeping it indefinitely also has a cost: duplicated
|
|
logic, ambiguity, security exposure, testing burden, and pressure to keep
|
|
building on an obsolete contract.
|
|
|
|
A published deprecation notice alone proves neither that callers received it
|
|
nor that they migrated. Raw request totals alone are also ambiguous: a request
|
|
successfully served by compatibility code is different from an attempt rejected
|
|
by a retired endpoint.
|
|
|
|
## Forces
|
|
|
|
- Callers need enough continuity to migrate without synchronized releases.
|
|
- Maintainers need a bounded path to removal rather than permanent dual support.
|
|
- Unknown callers cannot be coordinated directly until telemetry identifies
|
|
them.
|
|
- Caller guidance must be available at the point of use, not only in release
|
|
notes.
|
|
- Privacy and security constrain how caller identity and request data are
|
|
recorded.
|
|
- Infrequent but important callers can be absent from a short review window.
|
|
- A replacement that exists but has not been verified is not a safe successor.
|
|
- Once behavior returns a terminal response, attempted use still matters even
|
|
though no legacy work was successfully performed.
|
|
|
|
## Solution
|
|
|
|
Therefore, wrap the interface transition in an evidence-producing strangler:
|
|
|
|
1. Register the legacy interface, its owner, successor, lifecycle state, and
|
|
applicable hold or retirement policy.
|
|
2. Implement and verify the successor before restricting the legacy path.
|
|
3. Instrument the legacy boundary and communicate deprecation plus an actionable
|
|
successor reference on every use where the protocol permits it.
|
|
4. Record privacy-bounded usage evidence with enough outcome information to
|
|
distinguish served legacy traffic, redirects, terminal rejection, and
|
|
failures.
|
|
5. Move through explicit stages from compatibility to terminal retirement.
|
|
6. Keep a lightweight metered tombstone after terminal retirement so late
|
|
attempts reveal remaining callers.
|
|
7. Remove the tombstone only after the configured evidence gate passes and no
|
|
manual hold remains.
|
|
|
|
The meter and caller guidance are part of the interface lifecycle, not optional
|
|
observability added after the fact.
|
|
|
|
## Structure
|
|
|
|
```text
|
|
Caller
|
|
-> Legacy Boundary
|
|
-> deprecation and successor guidance
|
|
-> outcome-aware usage meter
|
|
-> compatibility implementation OR terminal response
|
|
-> Successor Interface
|
|
|
|
Interface Registry
|
|
-> owner + lifecycle + successor + verification + holds
|
|
|
|
Review Activity
|
|
-> usage windows + last-seen + caller attribution + outcome
|
|
-> migration action OR stage advance OR continued hold
|
|
```
|
|
|
|
The registry carries policy and identity. The meter carries observations. The
|
|
review activity turns both into a decision; it must not infer removal from a
|
|
calendar date alone.
|
|
|
|
## Dynamics
|
|
|
|
### Stage 1 — Announce and observe
|
|
|
|
Serve the old behavior, emit protocol-appropriate deprecation and successor
|
|
information, and establish a usage baseline. Contact attributable callers.
|
|
|
|
### Stage 2 — Migrate and narrow
|
|
|
|
Move owned callers to the successor. Stop adding capabilities to the legacy
|
|
surface. Narrow compatibility where doing so is reversible and observable.
|
|
|
|
### Stage 3 — Retire behavior, retain the tombstone
|
|
|
|
Return an explicit terminal result such as HTTP `410 Gone`, a typed CLI error,
|
|
or a rejected event subject. Continue returning successor guidance and metering
|
|
attempts.
|
|
|
|
At this stage a count means attempted use of a retired interface, not successful
|
|
legacy traffic. Dashboards and evidence must preserve that distinction.
|
|
|
|
### Stage 4 — Remove the tombstone
|
|
|
|
Remove routing and instrumentation only after the successor is verified, no
|
|
hold remains, and the evidence policy's quiet period has elapsed. Preserve the
|
|
registry history and decision evidence.
|
|
|
|
Any new use can stop or reverse a stage transition when the cost of doing so is
|
|
lower than breaking the caller.
|
|
|
|
## Invariants
|
|
|
|
1. Every legacy interface has an owner and an actionable successor reference.
|
|
2. The successor is verified before legacy behavior is terminally retired.
|
|
3. Caller-facing deprecation information travels on the legacy interaction
|
|
where the protocol supports it.
|
|
4. Metering failure does not silently turn absence of evidence into evidence of
|
|
absence.
|
|
5. Successful legacy service and rejected post-retirement attempts are not
|
|
reported as the same outcome.
|
|
6. A manual hold prevents automatic stage advancement.
|
|
7. Quiet periods account for expected caller cadence and historical volume.
|
|
8. Irreversible removal has retained evidence, rationale, and rollback or
|
|
recovery guidance appropriate to its risk.
|
|
9. Telemetry does not capture credentials or unnecessary request payloads.
|
|
|
|
## Evidence
|
|
|
|
The practice should produce:
|
|
|
|
- a registry record with interface identity, owner, successor, lifecycle state,
|
|
replacement verification, and holds;
|
|
- usage totals and bounded review windows;
|
|
- last-seen time and, where allowed, tenant/user/component or equivalent caller
|
|
attribution;
|
|
- request outcome or an unambiguous derivation from the interface lifecycle
|
|
stage;
|
|
- evidence that owned callers use the successor;
|
|
- the retirement threshold and its result; and
|
|
- the decision that advanced, paused, or reversed the transition.
|
|
|
|
Quiet-window policy should reflect use cadence. A high-volume interface that
|
|
has been quiet for one week may require a longer last-seen threshold than an
|
|
interface that was used once. Evidence should say why an interface is or is not
|
|
a retirement candidate rather than emitting only a boolean.
|
|
|
|
## Consequences
|
|
|
|
The organization gains a repeatable migration language, direct discovery of
|
|
unknown callers, and an evidence-backed point at which compatibility can end.
|
|
Late use becomes actionable information instead of a surprise outage.
|
|
|
|
The cost is temporary duplicate surface area, registry and telemetry storage,
|
|
review ownership, privacy design, and discipline around outcome semantics. A
|
|
tombstone has operating cost, but it is much smaller and safer than preserving
|
|
the full legacy implementation.
|
|
|
|
## Failure Modes
|
|
|
|
- **NoticeOnly:** publish a deprecation date without observing real use.
|
|
- **MeterWithoutMeaning:** count requests without distinguishing served traffic
|
|
from rejected attempts.
|
|
- **PermanentCompatibility:** meter forever but never define stage gates.
|
|
- **CalendarRemoval:** delete on a date despite contrary usage evidence.
|
|
- **UnverifiedSuccessor:** retire the old path because a replacement merely
|
|
exists.
|
|
- **SilentTombstone:** return a terminal response without successor guidance.
|
|
- **TelemetryBlindness:** treat a broken meter as a quiet interface.
|
|
- **IdentityOverreach:** collect payloads or personal data when coarse component
|
|
attribution would suffice.
|
|
- **ShortWindowConfidence:** miss monthly or quarterly callers by using only a
|
|
short quiet window.
|
|
|
|
## When Not to Use
|
|
|
|
Do not use the full pattern for an interface that was never released, has a
|
|
complete and controlled caller set that can be changed atomically, or must be
|
|
disabled immediately because continued exposure is an unacceptable security or
|
|
safety risk. In the last case, retire first and use the metered tombstone and
|
|
recovery guidance only where they do not preserve the vulnerability.
|
|
|
|
## Known Uses
|
|
|
|
### State Hub workstream-to-workplan transition
|
|
|
|
State Hub replaced legacy `workstream` REST terminology with `workplan`
|
|
interfaces. Its legacy registry records interface identity, owner, replacement,
|
|
verification, holds, and usage buckets. Legacy responses carry deprecation,
|
|
sunset, replacement, and successor-link metadata.
|
|
|
|
`GET /workstreams/{workstream_id}` is at Stage 3: it returns `410 Gone`, directs
|
|
the caller to `GET /workplans/{workplan_id}`, and records the attempt. The weekly
|
|
review therefore exposes remaining callers without implying that the retired
|
|
request succeeded. Retirement candidacy combines review-window traffic,
|
|
last-seen time, replacement verification, manual holds, and a quiet-period
|
|
ladder scaled by historical call volume.
|
|
|
|
Implementation references:
|
|
|
|
- repository: `state-hub`;
|
|
- compatibility behavior: `api/services/legacy_compat.py`;
|
|
- known route: `api/routers/workstreams.py`;
|
|
- evidence policy: `api/services/legacy_meter.py`; and
|
|
- operational description: `docs/workplan-terminology-transition.md`.
|
|
|
|
### Arc Nexus adoption
|
|
|
|
`arc-nexus` declares this PracticePattern as its policy for phasing out old
|
|
architecture registry interfaces. This is an adoption decision, not yet a
|
|
second implementation proof.
|
|
|
|
## Related Patterns
|
|
|
|
This pattern is a specialized strangler migration with an explicit evidence and
|
|
governance loop. Future related patterns may separate successor verification,
|
|
compatibility facades, evidence-gated removal, and consumer migration campaigns
|
|
once repeated uses justify independent names.
|
|
|
|
## Adoption Checklist
|
|
|
|
- [ ] Give the legacy and successor interfaces stable identities.
|
|
- [ ] Assign an owner and verify the successor.
|
|
- [ ] Define lifecycle stages, holds, and outcome semantics.
|
|
- [ ] Add caller-facing deprecation and successor guidance.
|
|
- [ ] Meter privacy-bounded usage and test meter failure behavior.
|
|
- [ ] Establish a review cadence and quiet-period policy.
|
|
- [ ] Migrate known callers and investigate unknown attribution.
|
|
- [ ] Retire behavior while retaining a metered tombstone.
|
|
- [ ] Confirm that evidence distinguishes attempted from successful use.
|
|
- [ ] Record the removal decision and preserve lifecycle history.
|
|
|
|
## Evolution
|
|
|
|
Version 0.1 generalizes the practice proven by State Hub's terminology
|
|
transition. The next useful evidence is a second implementation in a different
|
|
interface style, such as events, CLI commands, or schemas, to test which outcome
|
|
and successor fields should become structured canon concepts.
|