Architecture Migration Planning
Architecture migrations — splitting a monolith, moving to a new database, replacing a vendor, consolidating services, moving to the cloud — are among the riskiest projects a team undertakes. The classic failure mode is the big-bang rewrite: years of parallel development, a cutover weekend, a long list of forgotten behaviors, and a rollback to the old system that is now also out of date. Even successful migrations often stall at 80%, leaving two systems to operate indefinitely.
Successful migrations are incremental: the system keeps running and delivering value while it changes shape one slice at a time. Each step is small enough to verify and reverse, data moves with compatibility at every point, and the plan ends with the old system switched off, not just bypassed. This page covers how to plan and sequence such migrations.
TL;DR
- Start with why: the problem the migration solves and how you will know it worked.
- Map dependencies — callers, data flows, batch jobs, reports — before choosing the order of slices.
- Move one slice at a time with the strangler fig pattern and branch by abstraction, behind routing or feature flags.
- Move data with expand and contract, change data capture, and backfills; avoid uncoordinated dual writes.
- Verify with parallel runs, shadow traffic, and dark launches; define rollback for every step.
- Track progress publicly and finish with decommissioning: data, code, infrastructure, and access removed.
Quick Example
A migration plan for moving invoicing out of a monolith, written as a reviewable artifact:
The expand-and-contract steps for renaming a column without downtime:
Core Concepts
Start With the Reason and the Map
Write down the problem (deploy coupling, scaling limits, cost, end-of-life technology), the target state, and measurable success criteria. Then map what exists: inbound callers, outbound dependencies, shared tables, scheduled jobs, reports, data exports, and the people who rely on them. Most migration surprises are dependencies nobody listed. Record significant choices in Architecture Decision Records.
Slicing and Sequencing
Choose the first slice to learn, not to impress: a real but low-risk capability with clear boundaries. Later slices follow the dependency map, generally moving things that others depend on least first.
Moving Data
Plan reconciliation: counts, checksums, and sampled record comparisons between old and new stores, run continuously during the migration. See Database Migrations.
Compatibility
Clients and other services must keep working throughout. Keep old API contracts available (with adapters if necessary), version new contracts, preserve identifiers or maintain mapping tables, and keep URLs or redirects stable. For mobile clients and partners, compatibility windows last months.
Verification
- Parallel run: both systems process the same input; compare outputs before trusting the new one.
- Shadow traffic: mirror production requests to the new system without returning its responses.
- Dark launch: the new path runs in production for internal users or a small cohort.
- Cohort metrics: error rates, latency, and business outcomes compared between old and new paths.
Rollback and Risk
Every step needs a rollback that has been rehearsed — flipping a flag, rerouting traffic, or reversing replication. Steps without a cheap rollback (dropping data, changing ownership of writes) should come late, after confidence is high, and be scheduled with extra monitoring. Keep the old system able to take traffic back until the contract phase.
Finishing the Migration
Migrations stall when the last 20% is hard and the pressure is gone. Plan decommissioning as part of the project:
- Track the remaining callers and data consumers on a visible dashboard.
- Set a date for read-only mode and then removal of the old system.
- Delete code, tables, jobs, credentials, infrastructure, and monitoring for the old path.
- Update documentation, runbooks, and on-call ownership.
Best Practices
Deliver Value Along the Way
Choose slices that improve something users or developers feel, so the migration earns continued investment.
Keep One Writer per Piece of Data
Decide which system owns writes at each step, and synchronize the other through replication.
Automate Reconciliation
Compare old and new outputs continuously and treat mismatches as bugs to explain, not noise.
Budget for Decommissioning
Staff and schedule the removal of the old system explicitly; it is part of the migration, not an afterthought.
Common Mistakes
The Big-Bang Rewrite
Uncoordinated Dual Writes
Stopping at 90%
FAQ
What is the strangler fig pattern?
An incremental migration approach in which a routing layer gradually sends more functionality to a new system while the old one keeps handling the rest, until the old system can be removed.
What is branch by abstraction?
A technique for replacing a component inside a codebase: introduce an abstraction over it, move callers to the abstraction, build a new implementation behind it, switch over, then remove the old implementation.
How do I migrate data without downtime?
Use expand and contract: add new structures alongside old ones, synchronize with backfills and change data capture, move readers and then writers, verify, and remove the old structures last.
Should I do dual writes during a migration?
Avoid writing to both systems from application code, because partial failures cause divergence. Prefer a single writer with change data capture or the outbox pattern, and reconcile continuously.
How do I know a migration is done?
When success criteria are met and the old system's code, data, jobs, infrastructure, and access have been removed — not just when most traffic has moved.
Related Topics
- Cloud Migration Assessment and Execution — Inventory dependencies and choose migration, validation, cutover, and rollback steps.
- Architecture — Designing software systems
- Strangler Fig Pattern — Incremental replacement behind a router
- Database Migrations — Changing schemas safely
- Release Rollback and Database Compatibility — Keeping releases reversible
- Feature Flags — Controlling exposure during migration
- Monolith vs Microservices — Choosing a target architecture