Cloud Migration

Cloud migration is where a lot of money gets wasted – lifting a system to the cloud unchanged and then paying more for worse performance. Software Mile migrates applications the right way: assess first, choose the honest approach per workload, and move without stopping the business.

Not Everything Should Move the Same Way

Some systems just need rehosting. Some need re-platforming to use managed services. Some are worth re-architecting. And some should not move at all yet. We assess each workload and recommend per system – including the honest answer that a given application is not worth migrating right now.

How We Migrate

  • Assessment: inventory, dependencies, data volumes, and a cost model for the target
  • Phased migration that keeps systems running – no big-bang cutover unless it is genuinely safer
  • Data migration with validation, so nothing is lost or silently corrupted
  • Post-migration tuning so you actually get the cloud’s benefits, not just its bill

Tell us what you are running today and where you want it. We will assess before we recommend anything.

Which Workloads Should Move First?

Sequence is a design decision in its own right. The first workload to move should teach you something without hurting if it goes badly: real enough to exercise identity, networking, deployment, and monitoring, but not the system that stops the business if cutover slips a weekend. Moving the hardest thing first is how a program spends its budget before it has learned anything.

Coupling decides the rest. Applications that share a database or a file system usually have to move together or not at all, and discovering that during cutover is expensive. Assessment exists to find those clusters before anyone commits to a date.

When Is Lift-and-Shift Actually the Right Call?

Rehosting has a reputation it only half deserves. When a data center lease is ending, hardware is out of support, or a deadline is fixed by something outside your control, moving systems as they are and optimizing afterward is a legitimate choice. It buys time and removes a hard constraint.

It goes wrong in one specific way: when optimizing afterward is never scheduled or funded. Rehosting also changes the shape of what you pay, turning a sunk capital cost into a metered one, and how that lands depends on how well the old hardware was being used. If you rehost, put the re-platforming work into the plan and the budget at the same time, and give it an owner.

Why Do Cloud Bills Come In Higher Than the Estimate?

Migration estimates usually model compute carefully and everything around it loosely. The gaps tend to sit in the same few places, which is where an assessment should look before anyone signs off on a number.

Committed-use and reserved pricing help, but only once real usage patterns are visible. Buying commitments during a migration locks in the sizing you guessed at. Run on demand until the workload has settled, measure it, then commit to the shape you can see. The items below are the ones that surface during a move; the leaks that appear later in steady state are covered on our cloud services page.

  • Instances sized to match on-premise hardware that was bought for a peak years ago
  • Software licensing that changes terms, or price, when it runs on someone else’s hardware
  • The months when the old estate and the new one are both running and both billing
  • Moving the data itself, which is charged for and is easy to leave out of the model
  • Managed services priced per operation, which punishes code written for a local network

What Actually Goes Wrong at Cutover?

The servers are the part everyone plans for. The trouble usually comes from everything else that points at the old system: hardcoded IP addresses in scripts nobody owns, third-party allowlists that need the new outbound addresses, certificates tied to old hostnames, scheduled jobs on a machine that was never in scope, and reports that quietly stop arriving.

The counter is unglamorous. Inventory inbound and outbound connections before the date, shorten DNS records ahead of time, run old and new in parallel where the data model allows it, reconcile record counts and totals, and keep the ability to roll back until decommissioning the old environment becomes a deliberate decision.

Should You Commit to One Cloud or Stay Portable?

Designing for two providers at once means avoiding the managed services that make a platform worth using. That raises build cost and running cost in exchange for insurance against a move that may never be made, and the premium is paid every month whether or not the policy is ever claimed.

There are real reasons to run in more than one place: data residency rules, a contract that requires it, an acquisition that brought a second estate, or a service only one provider offers. Absent those, a single provider with infrastructure as code, portable data formats, and a documented exit path gives you much of the same protection without designing against the platform. Isolating one proprietary service behind a thin adapter is a different and far smaller thing, and it is usually worth doing. Our cloud application development page covers where that line sits.

What Has To Exist Before the First Workload Moves

Before any application can land, there is a foundation nobody asks for and that never appears in a workload inventory: an account structure, a network path, name resolution, an identity decision, and somewhere for logs to go. The first migration wave either builds that deliberately or improvises it under time pressure. It is built once and reused by everything that follows, which is why the first workload looks disproportionately expensive and the fifth does not, and why judging the whole program by the cost of wave one is misleading.

Addressing is the piece that is expensive to change later. On-premises networks were laid out years ago inside RFC 1918 space, and that space is small enough that an existing corporate range and a default cloud range collide regularly. If the two overlap, routing between them cannot be fixed at the routing layer; you get network address translation on the path, or you renumber one side. Every workload placed into the plan makes changing it harder, so the address plan is decided before anything moves, not after the third application is running.

Resolution and identity are the two that drag. Name resolution has to work in both directions: migrated systems still need to resolve internal names left behind, and on-premises clients need to resolve the new ones. Identity is a per-application question rather than one program-wide choice, and each application either keeps authenticating against a directory that has been extended into the cloud network, or is changed to federate with a cloud identity provider. Beyond addressing and identity, the items below are the ones that get deferred and then block a cutover date.

  • An account, subscription, or project structure with a tagging scheme that matches how you will want the bill broken down later, because retrofitting tags onto running resources is manual work nobody schedules
  • Connectivity sized for the migration transfer rather than for steady state: IPsec over the internet is capped per tunnel in the low gigabits per second, tunnels do not aggregate by default, and a dedicated circuit is provisioned in weeks, not hours
  • Conditional forwarding, or the provider equivalent, configured on the DNS servers on both sides before the first system needs it rather than during the cutover window
  • A destination for logs and metrics chosen and actually receiving data before anything production-facing lands, so the first workload is observable from the moment it starts
  • A defined non-production area, so cutover rehearsals do not run in the same account as the systems they are rehearsing for

The Database Usually Decides How Long the Outage Is

For most business applications the application tier can be built in advance and left idle at no risk. Data cannot. The cutover window is not the time it takes to start servers on the new side; it is the time to get the last consistent copy of the data across, load it, rebuild indexes, and verify it. Estimating that from database size alone is where plans go wrong, because the number is set by the narrowest point in the chain, whether that is the link, the read rate on a source that is still serving users, the write rate on the target, or the index build that only starts once the load finishes.

The standard way to shrink it is to seed and then follow. Take a bulk copy while the source stays live, then run continuous replication from the change log, so the target keeps pace with ongoing writes. Cutover then reduces to stopping writes at the source, waiting for lag to reach zero, and repointing the application. This depends on two things being true: the source has to expose a usable change stream, and every replicated table needs a stable way to identify a row. Tables without a primary key are a common reason a replication-based plan quietly reverts to a long copy window.

Two cases break the pattern. Changing database engines is not replication with extra steps; it is a conversion of types, collation behavior, and any logic that lives in stored procedures, and the testing dominates the schedule rather than the copying. The second is rollback. Once the new database has accepted writes, going back means replicating in the reverse direction, which few plans build and fewer test. If reverse replication is not in place, the rollback window closes at the first write on the new side, and that belongs on the plan as a stated limit rather than being discovered during the window.

Validating a Data Migration Beyond Record Counts

Reconciling counts and totals proves the rows arrived. It does not prove the values survived intact, because the failures that get past counting are the ones that change meaning without changing cardinality: a character set that substitutes on the way in, a time zone that shifts every timestamp by hours, a generator that restarts at one. These are worth checking explicitly the first time you move a given engine and schema, since each check below costs far less than finding the same problem after a month of new writes has been layered on top of it.

  • Content checksums on the tables carrying money, identity, or regulatory records: hash a canonical serialization of each row's columns on both sides and compare, so an altered value is visible where a matching count is not
  • Character set and collation on the target verified against the source, because a different collation changes sort order and can change what a unique index treats as a duplicate, and in MySQL the older three-byte utf8 will not store four-byte characters that utf8mb4 accepts
  • Time zone handling: whether the column type carries an offset at all, what the server and session time zones are on each side, and whether the application had been relying on the old server's local clock
  • Sequence, identity, and auto-increment generators advanced past the highest migrated key, since a bulk load inserts explicit values without moving the generator and the first insert after cutover collides
  • Constraints, triggers, and foreign keys that were disabled to make the load fast, confirmed re-enabled and validated against existing data rather than simply re-declared as trusted
  • Connection encryption and client driver versions on the new path, because managed endpoints commonly require TLS where the local server did not, which surfaces as a client library and certificate trust problem rather than a database problem

What the Migration Needs From Your Side

Access is usually the critical path. Read access to source systems, credentials or delegated accounts in the target, someone who can approve a firewall or network change without waiting a full change board cycle, and a named contact per application who can say what working means for that system. Access requests routed through approval queues can take longer than the technical work they unblock, and almost all of them can be started before assessment finishes.

Then there are decisions that are not ours to make. Acceptance criteria per system, stated as something checkable rather than as user satisfaction. Maintenance windows and freeze periods, including the ones set by finance and by contractual obligations rather than by IT. And who holds authority to call a rollback mid-cutover without convening a meeting, which should be one named person who is reachable, agreed before the window opens rather than negotiated inside it.

The dependency that gets underestimated is that part of the connection inventory cannot be discovered from your systems at all. Which partner holds your outbound addresses on file, who consumes an export, which auditor expects a file on a fixed date each month: that knowledge lives with people and in contracts, not in a configuration you can read. Collecting it takes calendar time and someone with the standing to ask across departments, so it runs in parallel with technical assessment rather than after it.

When Migration Is Not the Service You Need

Some estates do not have a migration in them. If the applications in scope are already vendor-hosted software as a service, there is nothing to move: the work is identity consolidation, integration between the tenants, and confirming your data export rights, which is a different engagement. If the driver is that one report is slow or one nightly batch does not finish in its window, moving the estate to rent faster hardware is an expensive substitute for profiling the query, and the problem usually follows the workload onto the new platform.

There is a narrower version of the same point. Where an application is already funded and scheduled for a ground-up rewrite, and nothing outside your control is forcing a date, meaning no lease ending, no hardware leaving support, and no externally fixed deadline, the target platform belongs in the new design rather than in a move the rewrite will discard. This is a different case from the re-platforming that should be funded alongside a rehost: re-platforming keeps the application and changes what it runs on, so a rehost is a step toward it, while a rewrite replaces the application outright. When one of those external constraints does apply, the constraint decides and moving first is still the right call.

Physical coupling is the clearest case of a system that should stay where it is. A server wired to equipment on a floor, a license enforced by a hardware key on a specific host, an instrument writing to a share over a local link: the application can move, but the thing it talks to cannot. What was a sub-millisecond call across a local switch becomes a round trip measured in tens of milliseconds over a link that also has its own maintenance schedule. Chatty designs that make hundreds of calls per transaction are where this shows up first, because added latency multiplies by call count rather than being absorbed once.

Frequently Asked Questions

Is modernizing an application part of a migration, or separate work?

Separate by default, even when the two are sequenced close together. A migration moves a workload to a new platform and proves it still behaves the same way, so the test is a comparison against known behavior. Modernization changes what the application does or how it is built, which is a different test surface and a different definition of done. Mixing them means that when something misbehaves after cutover, you cannot tell whether the platform or the code change caused it. Where a workload genuinely cannot run on the target without a change, that change is part of the migration and gets named per workload.

Who builds the cloud foundation, and does it have to wait for the assessment to finish?

It can be your platform team or ours, and it does not have to wait. Assessment produces the workload inventory and the sequence, but the foundation depends on far less than that, mainly the address plan and the identity direction, so the two run in parallel and usually should. If an account structure and connectivity already exist, the work becomes reviewing them against what the migrating workloads need rather than building again. Where your team owns the foundation, write the boundary down before the first wave, because who creates a subnet is the kind of question that stops a cutover cold.

Will we have to take an application offline to move it?

Usually a short window, occasionally none, and sometimes a long one that has to be scheduled honestly. An estimate is only worth as much as the rehearsal behind it, so the cutover gets run end to end against a restored copy of production rather than a sampled subset, because index rebuilds and validation on real volumes are exactly where estimates break. Some conversions have no online path at all, such as an engine change or a major version upgrade that rewrites storage formats on disk. Those are planned as a scheduled outage from the start rather than presented as a short one and then extended.

Can some systems stay on-premises permanently?

Yes, and hybrid as a steady state is a legitimate end state rather than an unfinished migration. It carries a standing cost: the link between the two sides becomes production infrastructure with its own capacity, failover, and maintenance, and identity has to work across the boundary continuously rather than just during a transition. Applications split across the boundary should have their chatty paths kept on one side of it. The decision worth making explicitly is which side is authoritative for any data both sides use, because two writable copies with a link between them is a synchronization problem, not a migration one.

What happens to backups and disaster recovery after the move?

They get rebuilt rather than carried over. Agent-based backup to an on-premises appliance, tape rotation, and storage array snapshots have no direct equivalent on the target; what replaces them is snapshot policies, point-in-time restore windows on managed databases, and object storage lifecycle rules, each with its own retention model and its own line on the bill. The number that matters is a completed restore test, not a green backup job, and the first restore test after a move frequently exposes a managed database whose default snapshot retention is measured in days where the old rotation covered months. Confirm as well whether copies need to live in a second region or a separate account, since a snapshot sitting beside the resource protects against failure but not against deletion.

Who decides which target platform and which services each workload lands on?

You do, and we give the recommendation with the reasoning behind it. A recommendation can be overruled by things outside the technical comparison, such as an existing enterprise agreement, a contractual or residency requirement, or an operations team that already runs one provider well, and those are valid grounds for choosing differently. Where a recommendation rests on data we could not obtain, such as usage figures nobody was collecting or a dependency the source system would not reveal, we say so rather than presenting an estimate as a measurement. Decisions made on incomplete information are workable as long as everyone knows which ones they are.