Skip to content
On this page

Plan and Track a Migration

This walkthrough takes a migration from "what does the new app still owe the old one?" to a confirmed answer. The old app is held as it is today and compared with the new one contract by contract. Each contract the new side lacks or reshaped becomes a work item under the migration's epic. The developers claim them from their repository, and the next /aspects run on the new app confirms each one by serving the contract.

It runs as the playbook Plan and track a migration (Playbooks). The site's page for the same job is Plan and track a software migration.

The example is Online store, a demo workspace of three apps from the eShop sample, each bound to its own repository: WebApp, Catalog.API and Ordering.API. The migration rewrites Ordering.API as a new Orders API in a second repository, bound to a second app board. The comparison reads what the Orders API still owes Ordering.API: its tables, its endpoints and the events it publishes.

Note

Owners and admins declare and edit comparisons. Every member reads them.

Before you start

  • The old app bound to its repository with its contracts extracted: /aspects has run for its tables, endpoints and channels (Aspects). The dialog won't hold an app with nothing pushed.
  • The new app's board, bound to its repository. Its contracts can be empty on day one: the comparison reads Missing until the code serves them.
  • An owner or admin role, to declare the comparison; an editor role to draft and hand off work items.
  • The code plugin installed where the developers work, signed in to the new app's board (The Code Plugin).

Start the run

Open More playbooks in the sidebar and choose Plan and track a migration. The guide opens with its steps in two stages: Author and Operate. The run works on an epic: type a name under Select an epic, here Orders rewrite, and choose Create. Every work item the run produces is filed under it.

Compare the old app with the new one

The first step opens the root board's Comparisons screen on New comparison.

Pick the shape

Choose the Rewrite preset. It fills one Bound app before, with Hold its contracts as of today ticked, and one Bound app after. For a monolith sliced into several services, a fold of several apps into one, or a database alone, pick that preset instead. Each fills the sides and narrows Compared by differently, and you can change anything it filled.

Name the sides

Under Before, pick Ordering.API. The row shows its repository, the branch its binding pins and what that branch last pushed. Held, it copies those contracts when you create the comparison, so the old side holds still while the new side moves. Under After, pick the Orders API: the table reads its contracts as they are pushed.

File it under the epic

Pick the run's epic under Epic, so the work items the comparison raises land in it, and choose Create comparison.

A preset fills the sides and the rules; the comparison itself stores only what you leave in the dialog.
  1. 1

    Before

    Under Before, pick Ordering.API and keep it held: it copies the contracts when you create the comparison.

  2. 2

    After

    Under After, pick the Orders API as a bound app: the table reads its contracts as they are pushed.

  3. 3

    Epic

    Pick the run's epic under Epic, so the work items the comparison raises land in it.

The step reads completed when the comparison names the epic. Its table opens on the headline. Every contract Ordering.API served is read as Kept, Changed, Missing or New on the Orders API, grouped under the Schema and API contract rules.

Read what the new side owes

The headline counts the old side's contracts: "N of M contracts kept". On day one of a migration most rows read Missing, and that is the plan. Each group is one change rule with its own counts.

  • A Missing row is a contract Ordering.API serves and the Orders API does not yet. A flag marks it under a critical rule, or when something outside the comparison calls it; Used by names that system.
  • A Changed row is served with a different interface: a parameter lost, a column dropped, a response status no longer returned. The reason names what differs.
  • A Kept row with a note has the same interface and a type or schema spelled differently. Under Interface strictness it is not a change. Not read names a field neither side cited, such as a column's nullability.
The table on day one is the migration plan: every Missing row is a step.

Turn the plan into work items

Open a Missing or Changed row's menu and choose Make a work item on the Orders API. The work item drafts on the new app with the old contract attached and the comparison's epic. One per contract, or one per group of contracts that land together. On the Work items screen, arrange them on the grid in waves: the tables first, then the endpoints that read them, then the events.

The run's Turn the plan into work items step completes when the epic holds a draft. Paste a written plan into Chat instead, and ProvenMap drafts the work items from it, anchored to the systems each step touches.

Hand the first wave off

Review the drafts and hand off the first wave with Hand off to Dev. Each becomes Open: locked, and visible to the developers' pulls. The rest stay drafts until their wave comes. The run's Hand the first wave off step completes when the first work item is handed off.

Build it

The developer works in the Orders API repository with the code plugin.

Claim a step

/work-items lists the open work items with their epic and the old contract each one asks for. Claiming one marks it In progress under the developer's name.

Build the contract

The developer builds the table, the endpoint or the publisher the work item names, and commits.

Extract

/aspects on the Orders API reads the comparison before it extracts. It looks for the contracts Ordering.API served first and records each one's interface where it finds it, then lists what else the repo serves. The summary says how many it found, how many it did not, and what else it read. A field it cannot cite stays empty rather than guessed.

/aspects --db The "Orders rewrite" comparison expects 7 tables: 6 of them are in this branch. requests isn't declared anywhere in the code; the comparison will show it. 4 tables added: buyers, cardtypes, paymentmethods, IntegrationEventLog. 2 updated.

See it land

Back on the comparison, the headline moves: the contracts the push served read Kept, and their work items complete on their own. Nobody resolved them: the /aspects run found the contract the work item asked for. The run's The first step is confirmed by the code step completes on the first one.

Each push moves the headline; a work item closes when its contract is served, not when someone says so.

A contract the migration drops on purpose stays Missing until you say so. Open its row and choose Accept as intended… with a reason. The row keeps its verdict, loses its flag and leaves the owed count. A contract that came back under another name is paired: Pair with a new contract folds the Missing row and the New row into one, marked paired.

Keep the old side honest

While the rewrite runs, Ordering.API keeps shipping. When it pushes a contract the hold lacks, the sets panel says so: "The app now serves 6 contracts this hold lacks". The table does not change on its own. Choose Update to latest to copy the old app's contracts again; the new rows join the plan as Missing.

Follow it from the hubs

While the comparison is open, it has a cell on the root hub's Comparisons card. The cell shows its verdicts as a bar and its headline, such as 5 of 14 contracts kept · 1 accepted. Select it to open the table. The Orders API's hub carries the chip Replaces Ordering.API (held) in its header, and its In comparisons card shows the same cell with the app's part (The Root Hub).

Check it worked

  • The headline reads every contract kept, or kept plus accepted, with nothing that breaks callers.
  • On Work items, every work item in the epic is Completed, with the day its contract was served. The run's Every step confirmed step reads done.
  • The Orders API's hub carries the chip Replaces Ordering.API (held), and the rewrite's cell on the root hub's Comparisons card reads the same headline as the table.
  • The Changes tab of the Orders API shows the weeks the contracts landed in, with the Schema and API contract rules' answers.

Close the comparison when Ordering.API is switched off. Its work items stay as ordinary work items on the Orders API.

What's next

Last updated November 9, 2026