The tooling for database migration is largely solved. Change data capture works. Reconciliation is a matter of writing careful queries. And yet migrations still go badly, because the hard part was never the technology — it is designing a cutover that a tired team can execute correctly at two in the morning.
Our first principle is that reversibility beats speed. Before we move anything, we establish how we would go back. If the rollback path is theoretical, we do not have one. That constraint shapes every subsequent decision, and it is why the legacy system stays warm and writable long after the switch.
The second principle is that divergence must be measured, not assumed. Change data capture keeps both estates in lockstep while an automated reconciler compares them row by row. We do not schedule a cutover until divergence has held at zero for a sustained period — typically two full weeks, including a month-end close.
The third principle is rehearsal. We run the cutover against production-scale data repeatedly, in full, until the timing stops being interesting. Nine rehearsals is not unusual. The goal is that the live run is the least eventful execution anyone has performed, because the team has already done it under worse conditions.
None of this is clever. It is a sequence of unremarkable decisions applied consistently. That is precisely why it works: the failure mode in migrations is rarely a missing capability, it is a step that someone decided to skip because the schedule was tight.