Skip to content

Plan and track a software migration

Usually an architect or platform engineer, with the team doing the rewrite

Put the old app beside its rewrite, contract by contract, turn what the new side still owes into work items in waves, and see each one land in the code.

The problem

A rewrite starts from a list of what the old system does, and the list is wrong. It comes from memory, from a wiki page written for the last rewrite, or from a spreadsheet of endpoints that nobody updated after the third sprint. The migration is declared done when the new system feels complete, and the first week in production finds the report that read a table nobody carried over.

Tracking the plan is the other half. Work items live in one tool, the code in another, and the question "which steps have actually landed?" is answered by asking around. With coding agents writing most of the new code, the gap between a step marked done and a step that is done has grown.

How it goes

The same steps the product’s playbook walks. Each one shows the screen at that moment.

  1. Put the old and new apps side by side

    Pick the shape of the move: a rewrite, a monolith split, a consolidation, a database move or an auth rewrite. The old app is held as it is today, so it holds still; the new app is read as it pushes. Every table, endpoint and event channel the old app serves is compared by its key and reads kept, changed, gone or new.

  2. Turn what is owed into work items

    On day one most rows read gone, and that is the plan. Each gone or changed contract becomes a work item on the new app, naming the contract it owes and filed under the migration's epic. Arrange them on the grid in waves: the tables first, then the endpoints that read them, then the events.

  3. Hand off the first wave

    Review the drafts and hand off the first wave to the team. The rest stay drafts until their wave comes, so nobody builds the third step before the first has landed.

  4. A developer claims a step

    In their coding session, a developer or their coding agent claims a work item, which names the contract it owes. The extraction on the new repository looks for the contracts the comparison expects before anything else.

  5. See each contract land

    The next extraction on the new app serves the contract, its row reads kept, and its work item completes on its own. The headline counts up, wave by wave, toward every contract kept. A contract the rewrite drops on purpose is accepted with a reason and leaves the count.

  6. Every step confirmed

    Done when every work item in the epic is confirmed by the code and the headline reads every contract kept or accepted. While the rewrite runs, the panel says when the old app has shipped a contract the hold lacks, so the plan never quietly falls behind the system it replaces.

  7. Proven by the code

    End proofDone when every contract the old app served is kept by the new one or accepted as retired, and every step is confirmed by the code.

Works with

Code
Both repositories read by the code plugin, which runs locally inside Claude Code, Codex or Cursor and pushes derived metadata, never your source.
Contracts
Tables, endpoints, event channels, pages and outbound calls, each with the file and line it was read from, and a field left empty rather than guessed when the code does not say.
Documents
An OpenAPI document or a DDL dump stands in for an old app nobody can bind, so a system with no repository still has a before side.
Work items
The plan in one epic, handed off in waves and claimed from a coding session; Jira and Slack when the team tracks work there.
Plans
Every step runs on the Free plan, including the confirmation by the code.

Where it stops

  • Contracts are compared by their keys: a table by its name, an endpoint by its method and path, a channel by its broker and name. The structure of the two apps, their services and dependencies, is not compared; a rewrite's structure is meant to differ.
  • A type or schema spelled differently reads as a note on a kept row, not as a change, unless the rule is set to read shapes. A field the extraction could not cite, such as a column's nullability, reads as not read and never as a change.
  • The held side is a copy of the old app's contracts as of a day. The panel says when the old app has moved on; Update to latest brings the new contracts in, and nothing joins the plan on its own.
  • Confirmation is structural: a contract is kept when the new code serves it with the same interface. Whether it behaves the same is not judged.

Why not a diagram, or a code browser

A diagram shows

The target architecture as someone drew it, with no list of what the old system serves and no way to say which of those the new one has reached.

A code browser shows

One repository at a time. It shows what the new code does, and nothing of what the old code did, so parity is a spreadsheet someone keeps beside it.

ProvenMap shows

Both apps read from their own code into one table, the old side held still, each contract kept, changed, gone or new. The plan, the hand-off and the proof sit on that table, and a work item closes when the code serves its contract.

Walk through it

  • The docs walkthrough of this job is being written.
  • In the product this job runs as the playbook Plan and track a migration. The board ticks each step when what it asked for exists.

Start with one system

Map a real system and see the architecture around it.

Open one repository and run the code plugin. No migration, no rollout, no diagramming.

No credit card · Analysis runs locally in your own session · Self-hosted available

See the four commands to your first board →

Or for writing on architecture that stays connected across systems.