A migration succeeds or fails on adoption, not on the availability of the new system — so manage it as a product with a funnel, a churn number, and a launch team, not as an infrastructure ticket with a due date. That means dual-running old and new, running an opt-in beta before any deadline, and tracking percent-migrated per team the way a growth PM tracks activation.

Quick Answer: Treat a platform migration roadmap like a product launch: define the "user" (each consuming team), run a dual-run + opt-in beta before any forced cutover, track adoption per team on a dashboard, and pair carrots (paved-path incentives) with a hard-stop deadline. Ship a rollback runbook before you ship the migration.

Why "just a migration" thinking gets infra PMs in trouble

Treating a migration as a one-time technical event — build it, flip the switch, done — is the single biggest reason migrations blow past their timeline. A migration is really a product with an adoption funnel: awareness, trial, activation, retention, and churn-back-to-old-system all apply. The teams you're migrating are your users, and users don't move because a system exists — they move because moving is safer and easier than staying.

This reframe matters because it changes what you measure. A ticket-based mental model tracks "is the new system live?" A product mental model tracks "what percent of traffic, teams, or accounts have actually cut over, and why is the rest stuck?" Those are different questions with different owners, and only the second one predicts whether you'll hit your date.

The tell that you're in ticket-mode, not product-mode: your only planning artifact is a build timeline, and "adoption" is a single line item near the end labeled "migrate consumers." If nobody owns activation and retention the way a growth PM would, the last 20% of consumers — the long tail with the gnarliest edge cases — will blow your schedule, because nobody built a funnel to find and unstick them early. This is the same discipline covered in our complete guide to the infra PM role: the job is influence over systems you don't fully control, and a migration is that dynamic concentrated into one project.

The migration-as-product framing, concretely

Product conceptMigration equivalent
UserEach consuming team, service, or customer account on the old system
AcquisitionAwareness that the new system exists and why it matters to them
ActivationFirst successful cutover of a real workload, not a test call
RetentionStaying on the new system under production load, not reverting
ChurnRolling back to the old system, or quietly never finishing
North-star metricPercent of traffic/teams fully migrated, trending toward 100%

The anatomy of a migration: dual-run, opt-in beta, forced deadline

Every well-run migration passes through three phases in order — dual-run, opt-in beta, forced deadline — and skipping straight to the third phase is the most common way migrations become incidents. Each phase has a different job: prove correctness, prove it under real usage patterns and win over your risk-tolerant early adopters, then convert everyone else on a schedule with teeth.

Phase 1: Dual-run

Dual-run means both systems process the same traffic simultaneously, with only the old system's output treated as authoritative, so you can diff outputs before anyone depends on the new one. This is your correctness gate, not your adoption gate — nobody should be asked to trust the new system yet. Practically, this looks like shadow traffic, dual writes, or a comparison job that flags divergence.

  • Duration: long enough to catch low-frequency edge cases — often 2-4 weeks minimum for anything with meaningful traffic variance (end-of-month batch jobs, regional traffic spikes).
  • Exit criterion: a defined, quantified divergence rate (not "looks fine"), reviewed against the error budget for the service you're migrating.
  • Common mistake: ending dual-run early because the demo looked clean. Demos exercise the happy path; production exercises the distribution's tail.

Phase 2: Opt-in beta

Once dual-run proves correctness, invite a small set of risk-tolerant, well-instrumented teams to actually cut over voluntarily — this is your product beta, and it should be treated with the same rigor: a named cohort, a feedback channel, and a bar for graduating out of beta. Beta teams are also your best source for anticipating the blockers the rest of the org will hit, which feeds directly into the adoption dashboard below.

Pick beta participants deliberately: teams with strong observability (so problems surface fast), teams with some slack in their roadmap (so a rollback doesn't wreck their quarter), and at least one team representative of the "hard" migration pattern, not just the easy one. A beta made entirely of easy cases produces false confidence.

Phase 3: Forced deadline

Only after beta has produced a track record does a hard cutover date become defensible — and it should come with a published decommission date for the old system, because an optional deadline is not a deadline. The forced phase is where carrots-and-sticks incentive design (next section) does its work, converting the long tail that opt-in alone will never reach.

A migration without a decommission date for the old system isn't a migration — it's a second system you now maintain forever.

Incentives: carrots and sticks for the migration laggards

The teams left after your opt-in beta didn't decline to migrate out of malice — they're rationally deprioritizing a project with no deadline and unclear payoff against their own roadmap, so your job is to change that calculus with both incentives and consequences. Relying on either alone underperforms: pure carrots let well-resourced teams migrate on their own schedule (helpful, insufficient); pure sticks breed resentment and rushed, buggy migrations late in the window.

Carrots that actually move teams

  1. Make the new path measurably easier, not just architecturally superior — better docs, a working starter template, a migration script that handles 80% of the boilerplate. Ulwick's Outcome-Driven Innovation research is a good lens here: teams adopt what reduces their effort against a job they're already trying to do, not what's merely "more modern."
  2. Offer white-glove pairing for the first few teams past beta — a fixed weekly office hour, or a named platform engineer who does the first PR with them. This is expensive per-team but cheap in aggregate if it prevents a stalled long tail.
  3. Publish a leaderboard or percent-migrated dashboard (next section) visible to leadership — social proof and mild competitive pressure move teams that a deadline alone doesn't.
  4. Retire toil, not just risk — if the old system requires teams to do manual reconciliation work today, message the migration as "this pain goes away," which is a stronger motivator than an abstract "it's more scalable."

Sticks that are fair and effective

  • A published decommission date, escalating in visibility as it approaches (team Slack, then team lead, then their VP).
  • Freezing new-feature support on the old system well before decommission, so teams building on it are visibly building on borrowed time.
  • Escalation to the org's actual prioritization process for teams that miss checkpoints — treat a stalled migration like a missed SLO, with the same seriousness you'd bring to speccing SLOs in the first place.
  • A firm "no exceptions without a written plan" rule — exceptions are fine, silent indefinite deferral is not.
LeverBest forRisk if overused
Better docs/toolingTeams with capacity but low priorityNone — always worth doing
White-glove pairingHigh-value or high-risk teamsDoesn't scale past a handful
Leaderboard/visibilityMid-pack teams, social proofCan feel punitive if handled carelessly
Decommission dateEveryone, especially the long tailPanic-migrations if announced too late
Feature freeze on old systemTeams stalling indefinitelyCan strand teams with real blockers

Building an adoption-tracking framework: the percent-migrated dashboard

An adoption dashboard for a migration needs exactly three views to be useful: an aggregate percent-migrated trendline, a per-team breakdown with status and blocker, and a projected-completion-date forecast — anything more elaborate becomes a status-reporting chore nobody keeps updated. The dashboard is your funnel report, not a vanity metric; it should drive the weekly conversation about who needs help.

What to track

  1. Percent of traffic/teams migrated, trending over time — not a single snapshot. The trendline's slope tells you if you're pacing to the deadline or need to intervene.
  2. Per-team status, using a small closed set of states: not started, dual-run, beta, migrated, rolled back. Avoid free-text status — it doesn't roll up.
  3. Per-team blocker, categorized (missing feature parity, no engineering capacity, unclear ownership, waiting on a dependency). Categorization is what turns this from a list into a management tool — it tells you whether the blocker is yours to fix or theirs.
  4. Time-in-status, flagging any team stuck in the same status for longer than your median. This is your early-warning signal, borrowed directly from sales-funnel "deal stalled" tracking.
  5. Rollback count and reason, tracked as its own metric — a rising rollback rate is a correctness signal, not just an adoption one.

Percent-migrated should be reported the same way you'd report activation rate for a consumer product: as a curve with a target date, reviewed weekly, with named owners for anything off-pace — not as a single number in a slide that updates once a quarter.

Mapping blockers to owners

A blocker log is only useful if every entry has an owner and a next action. "Waiting on platform team" and "waiting on our own capacity" require completely different interventions, so don't let a generic "blocked" status hide which side needs to move. This same team-by-team, blocker-typed view is the practical analog to a customer journey emotion curve — you're mapping where friction spikes for each cohort of "customer" and intervening at the specific step, not the whole journey.

Worked example: swapping an auth provider, with a rollback runbook

Auth-provider swaps are a useful worked example because they touch every consuming team, carry real security stakes, and make the cost of skipping dual-run painfully visible if sessions break. Below is a compressed version of how the three-phase anatomy and the incentive/dashboard framework apply to a real, common infra migration.

The scenario

You're moving from a legacy, self-hosted auth provider to a managed identity platform (OIDC-based), across dozens of internal services and a customer-facing app.

  1. Dual-run (4-6 weeks): Both providers issue tokens for a shadow percentage of logins; a comparison job diffs claims, expiry, and group-membership mapping. Exit criterion: divergence under an agreed threshold for two consecutive weeks, reviewed against your auth service's error budget.
  2. Opt-in beta (4-8 weeks): Two or three internal-tool teams with strong on-call coverage switch their login flow to the new provider behind a feature flag. Feedback loop: a shared channel, a weekly sync, and a running list of edge cases (service accounts, long-lived tokens, SSO edge cases) discovered during beta.
  3. Forced deadline (published at beta start, not after): All remaining teams have a fixed window, decreasing office-hour cadence at first then increasing again as the date nears, plus a feature freeze on the legacy provider's admin console starting at the midpoint.

The rollback runbook

A migration this consequential ships with a written, rehearsed rollback plan before cutover day, not one improvised during an incident — because auth failures are user-facing and time-pressured in a way that makes on-the-fly decisions risky.

  • Trigger conditions defined in advance: e.g., login failure rate above X% for Y minutes, or any token-validation divergence in production traffic.
  • Rollback mechanism: a feature flag flip back to the legacy provider per-service, not a code revert — rollback should be minutes, not a deploy cycle.
  • Session continuity plan: how in-flight sessions on the new provider are handled during rollback (forced re-login is usually acceptable for auth; it is not for, say, a database migration mid-transaction).
  • Communication template: pre-written status-page and internal-Slack language, so nobody drafts an incident update while also debugging.
  • Post-rollback review: a required retro before re-attempting cutover, distinguishing "this team's edge case" from "this is a systemic gap in our beta coverage."

The same discipline applies almost unchanged to a database migration (dual-write, shadow-read comparison, a forced cutover with a defined rollback window before the old database goes read-only) or a messaging-system swap. The anatomy doesn't change; only the specific divergence checks and rollback mechanics do.

Where a spec of both contracts earns its keep

One recurring failure mode in any migration — auth, database, or API — is that consuming teams don't actually know what's different between the old and new contract until they hit a break in production. This is where speccing the change explicitly, rather than relying on tribal knowledge or a changelog nobody reads, pays off directly.

Prodinja's API Designing tool lets you spec the old and new contracts side by side — endpoints, payloads, and behavior — so consumers can see exactly what changes before they commit to moving, instead of discovering it mid-cutover. For a migration where the "product" is really a contract change consumed by dozens of teams, having that comparison in one place is closer to a beta release-notes page than a Jira ticket, and it's the kind of artifact that shortens the opt-in beta phase because teams can self-serve the answer to "will this break me."

Key Takeaways

  • A migration is a product with a funnel — awareness, activation, retention, and churn (rollback) all apply, and the north-star metric is percent-migrated over time, not a binary "is it live."
  • Sequence dual-run, opt-in beta, then a forced deadline — skipping straight to a forced cutover without proving correctness and winning early adopters is the most common cause of migration incidents.
  • Pair carrots with sticks — better tooling and white-glove support move willing teams; a published decommission date and feature freeze move the long tail that incentives alone won't.
  • Track adoption with three views: an aggregate trendline, a per-team status-and-blocker breakdown, and a projected-completion forecast — anything more elaborate stops getting maintained.
  • Categorize blockers by owner, not just severity — "our capacity" and "their platform gap" need entirely different interventions.
  • Ship a written rollback runbook before cutover, with pre-defined trigger conditions, a fast rollback mechanism, and a communication template — improvising rollback decisions during an incident is how migrations turn into outages.
  • Spec old and new contracts side by side so consuming teams can see exactly what changes before they commit, rather than discovering it mid-migration.

Frequently Asked Questions

How long should a platform migration take from dual-run to decommission?

It depends on system criticality and consumer count, but a useful floor is 2-4 weeks of dual-run, 4-8 weeks of opt-in beta, and a forced-deadline window sized to your slowest realistic team — often 8-12 weeks for anything touching dozens of consumers. Compress any phase and you're trading schedule certainty for correctness or adoption risk.

What's the difference between a migration roadmap and a regular product roadmap?

A migration roadmap has a mandatory end state (100% migrated, old system decommissioned) and a real "churn" failure mode (rollback), where a normal product roadmap optimizes for growth without a forced finish line. The adoption-funnel thinking and per-cohort blocker tracking carry over directly from product management, per Jobs to Be Done style analysis of why teams delay.

How do you convince leadership to invest in a migration that has no visible new feature?

Frame it as retiring a growing liability — cite the compounding cost of running two systems, the error budget burn from the legacy system's known issues, and a concrete decommission date that stops the bleeding. This mirrors the case-building work in selling invisible infrastructure investment: make the counterfactual cost visible, not just the migration's cost.

What should trigger a rollback during a migration, and who decides?

Define numeric trigger conditions in advance (error rate, latency, divergence thresholds) so the decision isn't made under pressure by whoever's paged — ambiguity in the moment is what turns a rollback into a longer incident. The decision owner should be named in the runbook before cutover day, typically the on-call lead with a pre-authorized go/no-go.

Do all consuming teams need to go through the same opt-in beta before a forced deadline?

No — beta should include a deliberately small, representative cohort (including at least one hard case), not every team; the forced deadline phase is precisely how you reach the rest without waiting for universal voluntary buy-in. Trying to beta everyone just delays the forced phase and rarely surfaces new edge cases past a certain cohort size.