Everyone has heard the migration story. The weekend that became a week, the service nobody knew existed, the rollback that turned out not to work.
These failures are remarkably consistent in cause, which means they are largely avoidable.
Cause one: nobody inventoried what actually runs
The migration plan covers the application, the database and the file storage. It does not cover the scheduled job that emails the finance report, the internal tool someone built in 2019, the IP address a partner has allowlisted, or the certificate that renews from a script on the old server.
These surface during cutover, when there is no time to think.
The inventory is tedious and it is the highest-return hour of the entire project. Every scheduled task, every integration, every hardcoded address, every certificate, every cron entry.
Ask specifically: what runs on a schedule, what talks to us from outside, and what has our IP address written down somewhere? Those three questions surface most of the surprises.
Cause two: the cutover was never rehearsed
Build the target environment and run it in parallel. Point a copy of real traffic at it. Let it process a full weekly cycle including the scheduled jobs.
This is where you discover the timezone difference in the reporting job, the missing environment variable, and the integration that requires an allowlist update from a third party who takes four days to respond.
Finding those in a parallel environment costs nothing. Finding them during cutover costs the weekend.
Cause three: the rollback was theoretical
Every migration plan has a rollback section. Very few have a tested one.
Test it properly: switch to the new environment, then switch back, and verify everything works — including data written while the new environment was live. Data reconciliation is the part that catches people, because reversing infrastructure is easy and reversing a database that has taken writes is not.
The specific detail that decides your rollback speed is DNS TTL. If it is set to 24 hours, reversal takes a day regardless of how ready you are. Lower it several days before cutover.
A workable sequence
Migration sequence
Optimisation is deliberately last. Combining it with the move multiplies the failure surface.
- 1
Inventory
Everything running, including scheduled jobs and external dependencies.
- 2
Build parallel
Target environment stood up alongside, not replacing.
- 3
Rehearse
Run a full cycle in parallel, including all scheduled work.
- 4
Test rollback
Switch, switch back, reconcile data. Prove it works.
- 5
Lower TTL
Days ahead, so reversal is measured in minutes.
- 6
Cut over
Move, monitor, and only then begin optimising.
Migrate first, optimise second
The strong temptation is to redesign while moving — since we are rebuilding anyway, let us also containerise, re-architect the database and adopt a new deployment model.
This is how a two-week migration becomes a four-month project with an outage in the middle. When something breaks, you cannot tell whether the cause is the move or the redesign.
Lift and shift with minimal change. Prove stability. Then optimise as separate, reversible pieces of work.
When to schedule it
Not simply when traffic is lowest. When your team is available and rested, and when the third parties you might need are contactable.
A 2am Sunday cutover means the lowest traffic and the worst decision-making, with no vendor support reachable if something unexpected happens. Early on a weekday with the whole team present usually beats it.