mno tao
Okay, the title got me 😂 “The Deprecation Notice Nobody Reads” is way too real. But honestly, I really enjoyed how you turned something developers usually ignore into an actually interesting read. There’s something oddly satisfying about seeing those little engineering problems explained properly. Nice one!
The interesting shift here is treating API deprecation as an enforcement and telemetry problem rather than a communication problem. If the old endpoint continues returning 200 with no observable consequence, migration will naturally lose priority until the cutoff becomes an incident.
The per-consumer decision loop is particularly useful. Aggregate traffic can tell you that 8% of requests remain, but it doesn't tell you whether those requests belong to one critical payment integration or hundreds of dormant clients. That distinction should determine how aggressively enforcement progresses.
I’d also treat brownouts as a compatibility test, not just a forcing mechanism. The retry behavior, ownership gaps, and clients that ignore 429s can expose failure modes before hard retirement. That makes the deprecation process itself a form of production readiness testing.
The note that Deprecation is a Structured Field Date (@1735689600) while Sunset stays an HTTP-date is the detail most write-ups skip, good to see it spelled out.
Two related bits from the RFCs that fit the staged plan: RFC 9745 allows the Deprecation date to be in the future, so the header can ship in stage one before the endpoint is formally deprecated, and Sunset can't be earlier than that date. RFC 8594 also registers a separate rel="sunset" link relation, so the retirement policy page and the migration guide (rel="deprecation") can be two different links.
On brownouts returning 429: a client with an adaptive rate limiter reads that as "slow down", backs off, succeeds on retry, and nobody notices. A distinct error code in the body, like the one in your middleware, is what makes it show up in the consumer's logs as something other than throttling.