practice

Deprecation Brownout

also called Sunset Rehearsal, Scheduled Dark Window

An announced, time-boxed window in which a deprecated interface returns its retirement error, used to convert an abstract sunset date into a failure the consumer sees in their own monitoring.

salesforcedeprecationapi versioningmigrationsunset

Deprecation announcements move the customers who read announcements. They do not move the long tail: the integration nobody owns, running on a schedule, in an organisation where the person who built it has left. That tail is what makes retirement dates slip, sometimes by years.

A brownout attacks the tail directly. For a scheduled window — 30 minutes, then two hours, then a full day, spread over weeks — the deprecated version returns exactly the error it will return after retirement. Then it comes back.

The mechanism is that it changes who finds out. An email reaches a mailbox. A brownout reaches a failed job, an alert, and a support ticket raised inside the consumer's own organisation by someone with the access to fix it. It is the difference between telling somebody a date and showing them the consequence, while the consequence is still reversible.

Why it matters

It is the only deprecation instrument that produces information as well as pressure. After a brownout you know exactly who is still on the old version, because they called you. That list is the thing a retirement decision actually needs, and it is usually far more accurate than the telemetry.

It also rehearses the retirement itself. The turn-off path gets exercised, the error body gets read by real integrators, and any dependency you had forgotten — an internal service quietly using the old version — surfaces while rollback is one configuration change away.

Implementation patterns

  • Announce every window in advance, with dates, duration and the exact error. A brownout nobody was told about is an outage.
  • Escalate the duration: 30 minutes, then 2 hours, then 24 hours, with weeks between. The first is a nudge, the last is indistinguishable from retirement.
  • Exempt nothing quietly. If a customer gets an exemption, record it and put an end date on it, or the exemption becomes the new permanent state.
  • Return the real retirement error — 410 with a body naming the sunset date, the replacement and a link — so the integrator debugging it is handed the fix rather than a status code.
  • Pair it with Deprecation and Sunset headers on ordinary responses (RFC 8594) so tooling can detect the state without a human reading a blog post.
  • Publish a rollback commitment: how quickly you will end a window early if the impact exceeds a stated threshold.

Industry example

Salesforce scheduled the retirement of Platform API versions 21.0 through 30.0 for the Summer '23 release and later postponed it to Summer '25, carrying the notice forward through successive release notes, having retired versions 7.0 through 20.0 in Summer '22; a retired version returns 410 Gone on REST. A postponement of that size is the general case rather than an anomaly: for a platform whose customers integrate deeply and upgrade slowly, the binding constraint is residual traffic, not the calendar, and the instruments that move residual traffic are the ones that create a visible failure.

Failure scenarios

  • An unannounced brownout, which is an outage with a euphemism attached and permanently damages the trust the programme depends on.
  • A window too short to be noticed by batch integrations that run nightly, so the tail is untouched and the team concludes brownouts do not work.
  • No telemetry during the window, so the exercise produces pressure and no list.
  • Exemptions granted under escalation without end dates, after which the retirement is permanently blocked by three customers.
  • Brownout on an interface with life-safety or payment-critical consumers, where the reversible-consequence assumption does not hold.

Trade-offs

Choose Gains Pays
Brownouts Real migration pressure; an accurate list of remaining consumers; a rehearsed turn-off Support load in a known window; trust cost if communication is poor
Announcements only No deliberate breakage; low operational effort The long tail does not move, and the date slips

When not to use it

Where a short failure is not recoverable for the consumer, a brownout is not a rehearsal, it is harm: clinical systems, payment authorisation during a peak trading window, anything with a regulatory availability obligation. There the instruments are per-consumer outreach, contractual deadlines and, where necessary, paid extended support.

And for internal interfaces with known consumers, skip it entirely. Contract tests name every caller, a coordinated change takes weeks, and deliberately breaking a colleague's service to make a point is a governance failure rather than a technique.

Interview question

Q: You announced the retirement of v1 eighteen months ago. Traffic is down 80% and the remaining 20% comes from customers who do not answer emails. What do you do next, and what would you have built earlier?

What a strong answer covers: that the constraint is residual traffic rather than the date; escalating announced brownouts as the instrument that reaches people who do not read announcements; using the window to collect an accurate consumer list from inbound tickets; the error body carrying the fix; sunset headers for tooling; and the thing to have built earlier — per-consumer usage telemetry at version granularity with a contactable identity attached.

Quick check

Quiz: Why does a brownout move migration when six months of emails did not? Because it produces a failure inside the consumer's own monitoring, reaching the person with access to fix it rather than a mailbox, while remaining reversible.

Flashcard: What is the escalation shape of a deprecation brownout? Announced windows of increasing length — roughly 30 minutes, then 2 hours, then 24 hours, weeks apart — each returning the real retirement error, with telemetry captured so the remaining consumer list comes out of the exercise.