Every API old enough to matter eventually needs a migration: a new data model that doesn't fit the old shape, a monolith split into services, a legacy system finally being retired after years of everyone agreeing it should be. The instinct under pressure is to plan the destination carefully and treat getting there as a footnote — build the new system right, then do a cutover weekend. That instinct is exactly backwards for anything with real traffic and real consumers, because the cutover weekend is where almost all migration failures actually happen: a big-bang switch has no partial-failure state, no way to verify the new system handles real traffic correctly before it's the only system handling it, and no calm path back if something's wrong.
The alternative this lesson builds toward isn't more caution for its own sake — it's a different shape of risk entirely. Instead of one large, irreversible decision made at 2 a.m. on cutover night, a well-run migration is a long sequence of small, individually reversible decisions, each one verified against real production behavior before the next one depends on it. The new system runs alongside the old one, proving itself on real traffic while the old one keeps serving, and the actual cutover — when it finally happens — is almost anticlimactic, because every real risk was already found and fixed while the old system was still there as a safety net.
This connects directly to versioning and deprecation, covered earlier in this course, but a migration is a bigger commitment than a routine version bump: it usually touches every consumer, takes months, and has real organizational cost if it stalls halfway. What follows is a set of concrete techniques — the strangler fig pattern, shadow traffic, expand-contract schema changes, and a disciplined rollback plan — for making that commitment survive contact with a production system that, inconveniently, has to keep working the entire time you're changing it underneath.