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

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

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:

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

References