Product Version Migration Plan
A migration announcement sent to everyone reaches 1,238 accounts with nothing to migrate and manufactures the tickets it was meant to prevent.
Free download · No account needed
This pack derives the cohorts from event data on the exact capability being retired, then joins them against the capability gap between the old version and the new one. Usage alone gives you heavy users. The gap list alone gives you missing features. The join gives you the accounts that cannot move today, who they are, and which gap is holding each one. In the worked example that is 51 accounts out of 1,842.
Deprecation policy is a solved problem in infrastructure and an unsolved one in product. Kubernetes fixes the window in its own policy text: a beta API is no longer served nine months or three minor releases after deprecation, whichever is longer. Microsoft's Modern Lifecycle Policy commits to a minimum of twelve months of notice before support ends where no successor is offered. Both set the date. Neither tells you who to tell first, which is the part that decides the support load.
In the worked example, 61.7 percent of the heaviest cohort is blocked against 1.3 percent of the lightest, so a single announcement reaches both with the same message. Staging it costs 189 tickets against 268, and the peak week needs one support person rather than five. Built to sit after the spec for the replacement and beside the stories engineering is building from, for the fortnight before a retirement date goes public. It is not a sunset with no replacement, which is a different job.
What is in the pack
Capability Gap Map with usage on every row
Every capability of the old version, whether the new one covers it, how many accounts used it in the window, and how many of them it is the only thing blocking.
The middle category nobody names
Capabilities that survive and change shape. They block nobody, they appear on no list of what is missing, and they are the leading source of tickets in a typical migration.
Cohorts derived from events, not from plan tier
Deep, regular, occasional and never opened it, with the event count and the window written into the sheet so nobody has to remember what a cohort meant six weeks later.
The join, reported as a rate per cohort
Blocked accounts inside each usage band, plus the split between the ones a ship date fixes and the ones that need a named person and a call.
Support load priced before the comms are drafted
One announcement against staged waves, using rates from whatever you retired last, converted into people per day rather than a total nobody can act on.
Objection Register with a count and an answer
Every objection with who raised it, how many accounts have raised it, the answer given, and whether the plan changed. Two normally should.
How it works
- 1
Send the change
Whatever engineering wrote, especially anything describing what the new version cannot do yet.
- 2
Add the usage export
Account id and an event count over ninety days is enough. An entitlement list is not a substitute.
- 3
Read the join
Blocked accounts by usage cohort, deduplicated across gaps, split into the ones a date fixes and the ones that need a person.
- 4
Price it, then write
One announcement against staged waves, in people per day, and the wave plan falls out of the number.
Frequently asked questions
What do I need before this is useful?
Whatever engineering wrote about what the new version does not do yet, plus a usage export for the feature being retired. Account id and an event count over ninety days is enough. An entitlement list is not a substitute: those two populations differed by 1,238 accounts here. An adoption review is one place to get the export.
Why not just announce it to everybody?
Because two thirds of the entitled base has nothing to migrate, and contacting them manufactures tickets. At the previous retirement's rate that is about 25 tickets from 1,238 accounts, none matching any migration work. The bigger cost is concentration: one send lands 187 tickets in 72 hours, which is five people on a team of four.
Is it safe to send nothing to the accounts that never opened it?
They have zero events in the window, so there is no saved work to move and no schedule to rebuild. The change still goes in the release notes and the changelog, and anybody who opens the old surface sees an in-product notice from week zero. That is the safety net.
Our heaviest users are the ones who get hurt. Is that normal?
It is structural rather than bad luck. The capabilities a new version has not reached yet are the ones only sustained use ever finds, so exposure rises with commitment. In the worked example 29 of 47 deep users were blocked against 5 of 394 occasional ones, a 49-fold difference a single announcement cannot address.
What actually generates the most tickets?
Not the missing capabilities, because those accounts already have a named owner. It is the capabilities that survived and changed shape: branding moved to account settings, permissions moved to roles, formula syntax changed. All three are covered, none appears on a gap list, and together they explain most of the volume.
Does this set the retirement date?
The other way round. The date is a decision the gap map should inform, so nothing goes in the sheets until the join exists. Committing first is how a plan promises a date while thirty accounts wait on something unbuilt. Engineering's own estimates belong in a feasibility brief before the date is fixed.
Find out how many accounts actually cannot move
Send the change and a usage export for the thing being retired. What comes back first is the gap map joined to the cohorts, and the blocked rate inside each one.
Build my cohorts