Skip to content

Migrating a client onto your hosting platform: waves, cutover and a rollback you can use

Who this is for. MSP project leads and engineers who are moving an existing client estate (from on-premises servers, another host or a previous provider) onto a platform you operate, and who want the move to be boring. A migration has three parts: copy the data, switch the users, and be able to go back. The third part is the one that gets skipped.

Discovery: find what nobody wrote down

The migration plan is only as good as the inventory it starts from. Per server, capture:

  • Role, operating system and version, installed applications and their versions.
  • Resource use at peak, using the method in virtual servers and capacity planning, so you can place it on the target.
  • Data volume, rate of change, and the largest single file or database.
  • Network facts: IP address, whether it is hard-coded anywhere, firewall rules in and out, DNS names that point to it.
  • Dependencies: what talks to it, and what it talks to. Include scheduled tasks, mail relays, license servers, printers and scanners, service accounts, certificates and anything that authenticates against it.
  • Licensing and support position, including whether the vendor supports the application in the target environment.
  • Business facts: who owns it, who signs off after the move, the acceptable outage window and what the business cost of exceeding it is.

Hidden dependencies are the usual cause of a failed cutover. Gather them by reading firewall logs and connection tables for a few weeks, rather than relying on memory. Two read-only commands help for a Linux or Windows server you administer:

# Linux: who is connected to this server right now, grouped by remote address
sudo ss -tn state established | awk 'NR>1 {print $4}' | sed 's/:[0-9]*$//' | sort | uniq -c | sort -nr | head
# Windows: established TCP connections, with the owning process
Get-NetTCPConnection -State Established | Sort-Object RemoteAddress |
  Select-Object LocalPort, RemoteAddress, RemotePort, OwningProcess

A snapshot is a start, not a survey. Repeat over a full business cycle, including month-end if that is when the odd job runs.

Wave design: order by dependency and risk

Do not migrate everything at once and do not migrate in alphabetical order. Group servers into waves by dependency (things that depend on each other move together or in a defined order) and by risk (low-risk first, to find mistakes cheaply).

WaveContentsPurpose
0A non-critical server, or your own test tenantProve the platform, the network design and the runbook
1Low-risk, low-dependency systemsExercise onboarding, backup and monitoring at small scale
2Shared services (identity, file, print)Move what many things depend on, with extra care and rollback readiness
3Applications and databasesThe business-critical systems, once the supporting pieces are proven
4DecommissionRetire the source only after an agreed acceptance period

Keep waves small enough that you can roll one back without rolling back the others.

Choosing how to move the data

ApproachGood forWatch for
Convert and restore the whole virtual machineServers with complicated software, little downtime sensitivityDriver and hardware-dependent configuration; the downtime is the copy time
Replicate continuously, then cut overLarger systems and tight outage windowsNetwork bandwidth, and replication that adds load to the source
File-level synchronisationFile serversPermissions, hard links, open files and exact security descriptors
Application-level migration (native database replication, application export)Databases and applications with supported migration pathsVersions, features that differ between source and target
Rebuild fresh and migrate the dataOld systems you do not trustTime, and hidden configuration lost in the rebuild

Each approach has a seed (the long first copy while the source stays live) followed by one or more delta passes, with a final short pass during the outage window. The shorter the delta, the shorter the outage.

A file-level example with sample paths and hostnames. Run the dry run first and read what it says:

# Dry run: shows what WOULD be copied, changes nothing
rsync -aHAXn --numeric-ids --info=progress2 -e ssh /srv/data/ migr@new-host:/srv/data/

# Real seed copy (no --delete). Re-run the same command for each delta pass.
rsync -aHAX --numeric-ids --info=progress2 -e ssh /srv/data/ migr@new-host:/srv/data/

Adding --delete to rsync, or using /MIR with robocopy, removes files on the destination that are not on the source. Use it only on a final pass, only when you are certain of the direction and the paths, and only after a dry run.

# Windows file server: first, list only (no copy), then copy with security descriptors preserved
robocopy \\old-fs\share D:\share /E /COPYALL /DCOPY:DAT /R:1 /W:1 /L /LOG:C:\migr\dryrun.log
robocopy \\old-fs\share D:\share /E /COPYALL /DCOPY:DAT /R:1 /W:1 /LOG+:C:\migr\copy.log

For disk images, qemu-img converts formats without altering the source, and writes a new file:

qemu-img info source.vmdk
qemu-img convert -p -f vmdk -O qcow2 source.vmdk dest.qcow2
qemu-img check dest.qcow2

Verify copies with checksums rather than trusting file counts:

# On the source
(cd /srv/data && find . -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/manifest.sha256)
# Copy manifest.sha256 to the target, then there:
(cd /srv/data && sha256sum -c --quiet /tmp/manifest.sha256)

Estimating the seed and the outage

Two numbers drive the plan: how long the seed copy takes and how long the final outage lasts. Estimate both from measurement, not from the link speed printed on the contract. Copy a representative sample, note the sustained rate you actually achieve (small files are usually far slower than large ones), and divide.

Worked example with invented numbers. A file server holds 2 TB (about 2,000,000 MB) and a test copy sustains 100 MB/s. The seed takes 2,000,000 / 100 = 20,000 seconds, roughly 5.6 hours, and you can run it while users work. Suppose users change 20 GB a day. The final delta of one day’s changes is 20,000 MB / 100 MB/s = 200 seconds plus scanning time, so the outage window is dominated by scanning, stopping services and verification rather than by data. If the sustained rate were ten times lower, the seed would take more than two days and you would need to start sooner and run several delta passes, which is a different plan. Estimating first tells you which plan you are in.

Telling the client what will happen

A technically clean cutover still fails if the client is surprised. Agree in writing, before the night: the outage window and the decision point, the acceptance test and who runs it, what the client must do (log off, stop a batch job, confirm that nobody is working late), and who is reachable by phone throughout. Agree a change freeze on the source and on anything that depends on it from the final delta until acceptance. After the move, send a short summary of what changed (addresses, names, backup schedule, support contacts) so that the next incident does not begin with confusion about where the server lives.

Network and name cutover

Decide how users will find the server after the move:

  • Keep the IP address by extending the network, or by moving the address with the server. It reduces the number of things that change. It also means your platform must carry the client’s address plan; see the address-planning notes in private cloud.
  • Change the address and update DNS. Lower the DNS time-to-live well before the cutover, by at least the old TTL, so that caches have expired by the time you switch. Check what resolvers actually hold:
dig +noall +answer app.example.com A     # the number before IN is the remaining TTL in seconds
Resolve-DnsName app.example.com -Type A  # Windows; shows TTL as well
Test-NetConnection app.example.com -Port 443
  • Plan the certificates, firewall rules, VPNs and any IP allow-lists at partners that reference the old address. Those are outside your control and often the slowest to change; start early.

A cutover runbook skeleton

Write the runbook before the night and rehearse it in wave 0. Each line has an action, an owner, a check and a rollback trigger:

WhenStepOwnerCheckRoll back if
T-7 daysLower DNS TTL; confirm seed copy completeEngineerTTL reflects change; delta size knownSeed not complete
T-1 dayFinal delta; backup of source and targetEngineerBackup verifiedBackup fails
T-0, startStop writes on source; final delta passEngineerChecksums matchMismatch unexplained
T-0Start target; change DNS or addressEngineerServices start; names resolveService fails to start
T+30 minClient acceptance testClient contactAgreed test script passesTest fails
T+1 hourGo or roll back decisionProject leadNamed decisionPer script
T+1 dayBackups, monitoring and patching confirmed on targetEngineerReports show targetn/a

Set a decision point with a time, and have the decision maker named. Without it, the team will spend three hours debugging at the point where the right call was to go back.

Rollback design

A rollback is only real if you have kept the source intact and decided what happens to data written after the cutover. Leave the source powered off or isolated but unchanged until the acceptance period ends. If users have already written new data on the target when you roll back, you have a reverse-sync problem; decide in advance whether that data matters and how it returns. For databases, rolling back after the application has run on the target often needs a replication path in the other direction, so plan it before you need it.

Onboarding to the platform after the move

The move is not finished until the server is a platform citizen:

  1. Backup in place at the right tier, with a first restore test, per backup and recovery.
  2. Monitoring tagged with the tenant, and alert routes confirmed.
  3. Patch group and maintenance window agreed with the client.
  4. Address register, documentation and administrator access updated and reviewed.
  5. Resource limits set to match what you sold, and metering started so billing matches.
  6. The source retired on schedule, with its data securely deleted and the deletion recorded.

Common mistakes

  • No acceptance test written in advance, so “it works” is an opinion at 2 a.m.
  • Skipping the dry run and copying in the wrong direction.
  • Discovering a hard-coded IP address during the outage window.
  • Changing too much at once: new platform, new addressing, new software version in a single night.
  • Decommissioning the source early because the cutover looked fine.
  • Forgetting that the contract for the old provider has notice periods, and overlapping cost while you migrate. Check the exit terms in evaluating a hosting provider.

What to do next

Write the inventory for your next client move, group it into waves, and draft the runbook before you schedule anything. The requirements planner helps you state what the receiving platform must provide before you commit a tenant to it.