Move a boundary, not a slogan
An incremental migration is not a promise that every old component will disappear quickly. It is a way to move one understandable boundary at a time while the remaining system continues to do real work.
The first useful question is which part of the current flow can be changed without making correctness or recovery harder to explain.
Choose a safe slice
A migration slice is easier to review when it has:
- a clear input and output;
- a defined owner for the behavior that remains in the old path;
- an observable handoff between old and new processing;
- a rollback or replay path that does not depend on guesswork.
Jobs that encode business rules or have weak test coverage may need to stay in the old path until those conditions improve. Leaving them in place is a boundary decision, not a failure to migrate.
Make retries intentional
Retries are part of the design whenever a pipeline can fail after partially completing work. Idempotent load boundaries, explicit run identifiers, and logs that show the affected environment or data slice make replay safer to reason about.
The goal is not to eliminate every failure. It is to make a failed run distinguishable from a successful run that only appears complete.
Treat evidence as a release condition
Move the next slice only when its tests, logs, and sign-off process are ready. A smaller migration with an inspectable result is more useful than a larger migration that leaves operators unsure which path produced the data.
This keeps the old system visible as a temporary dependency while the new path earns trust through evidence.