Key takeaways
  • The cloud migration challenges that derail programmes are rarely technical unknowns. They are known-but-unowned items: an undocumented integration, a licence clause, a team that was never asked whether it could operate the result.
  • Application dependency mapping produced from a CMDB is a starting hypothesis, not an inventory. The connections that break a cutover are the ones nobody registered: a nightly file drop, a hard-coded IP, a partner pulling a report.
  • Identity is the dependency that touches every workload and is planned as if it touched one. Moving an application without moving how it authenticates is how a migrated system ends up unreachable by the people who need it.
  • Data gravity sets the sequence. A dataset that several systems read cannot move alone, and the cost of a split estate is paid in egress and latency for as long as the split lasts.
  • Software licensing terms change value the moment infrastructure is virtualised or moved to a third party. Reading contracts is a migration task, not a procurement afterthought.

Migration plans tend to be written around the challenges that are easy to name: sizing, network throughput, downtime windows, tooling. Those get budget and owners. The cloud migration challenges that consume the schedule are different in kind. They are the items that everyone half knows about, that appear in no register, and that surface three weeks before a cutover when someone finally asks the question nobody had been assigned to ask. This article covers the ones we see repeat across migration programmes, and what a plan looks like when it accounts for them.

The dependency map is a hypothesis

Every migration starts with an inventory. Usually it comes from a CMDB, a discovery tool, or a spreadsheet maintained by the infrastructure team. The document is treated as a description of the estate. It is closer to a description of the part of the estate that was written down.

What the inventory reliably contains: servers, their sizes, their owners on paper, the applications that were formally commissioned. What it reliably misses is the connective tissue built by people solving problems on a Tuesday afternoon over a decade:

  • A scheduled job on a workstation under a desk that drops a CSV into a shared folder every night at 23:00, and a downstream system that has silently depended on that file since 2016.
  • A hard-coded IP address in a configuration file, written before DNS was consistent internally, which resolves nothing after the move.
  • An external partner with a read-only database account, used to pull a monthly report, granted by someone who has since left.
  • A reporting tool connecting directly to a production replica rather than through the warehouse, because the warehouse was slow that quarter.

None of these appear in a discovery scan of running processes if the job runs monthly and the scan ran on a Wednesday. They appear at cutover, as an incident.

The practical answer is to treat the inventory as version zero and spend real effort turning it into an observed map: network flow logs over a period long enough to capture monthly and quarterly cycles, database connection audits by account rather than by application, and structured interviews with the people who operate the systems daily rather than the people who own them on the org chart. That effort is unglamorous and it is the difference between a cutover plan and a guess. Our IT consulting engagements usually start here, because the rest of the plan is derived from this map and inherits its errors.

Identity is the dependency under every other one

Authentication and authorisation are planned as a workstream among others. In practice they are a precondition for every workstream. An application moved to a new environment still has to know who is calling it, and the people calling it still have to reach an identity provider that trusts both sides.

The failure modes are consistent. A directory that was reachable because everything sat on the same internal network now needs an explicit, secured path. Service accounts authenticating by machine identity on a domain-joined host stop working when the host is no longer domain-joined. Group memberships that granted access implicitly, through inheritance nobody has looked at in years, do not survive a re-modelled directory. Certificate trust chains that were installed manually on servers years ago exist on no image.

The pattern we recommend is to treat identity as the first migrated capability rather than a parallel one. Establish the target identity model, get it running and trusted, and migrate applications onto it before or during their move, not after. Federated access and a centrally managed provider, whether that is Keycloak or a managed alternative, removes an entire category of cutover incident, because the question "can the users still get in" stops being answered per application.

The cost of getting this wrong is not usually a security incident. It is a migrated system that works perfectly and that nobody can reach, discovered on the Monday morning after a weekend cutover.

Data gravity decides the order, whether you plan it or not

An application can be moved in a weekend. The dataset it depends on often cannot, and more importantly, that dataset usually has other readers.

The result is a period, sometimes a long one, where a database sits on one side and several of its consumers sit on the other. Every query crosses the boundary. This produces three costs at once: latency that changes application behaviour in ways load testing did not reproduce, egress charges that grow with usage rather than staying fixed, and a network link whose failure now takes down systems that used to be independent of the network.

Two things follow. First, the migration sequence should be derived from data dependencies rather than from application ownership, which means grouping systems into move-together sets even when they belong to different business units with different appetites. Second, the duration of any split state belongs in the business case as a cost line, because it is one. A six-week split is a rounding error. A nine-month split, which is what happens when one system in the group has an unresolved licensing or vendor question, is a budget item nobody approved.

We cover the decision framework behind this sequencing in more detail in our article on cloud migration strategy, where the per-system disposition and the order of moves are treated as the two decisions that set the final bill.

Licensing terms change value when the infrastructure moves

This is the challenge with the highest ratio of financial impact to attention received, and it is not a technical problem at all.

Enterprise software contracts written for physical, on-premise deployment frequently contain terms that behave differently once the workload runs on shared or third-party infrastructure. Licences counted per physical core interact badly with hypervisors that can theoretically schedule a workload anywhere in a cluster. Terms restricting deployment to hardware controlled by the licensee have a specific meaning when the hardware belongs to a hyperscaler. Support entitlements sometimes lapse for configurations the vendor has not certified. Database licences in particular have clauses whose interpretation can multiply a cost line without a single technical change.

None of this is hidden. It is written in contracts that live with procurement or legal and that the migration team has usually not read. The remedy is procedural: pull every licence agreement for in-scope software at the start of the assessment, get a reading on the cloud clauses, and price the outcome per system. Where a licence makes a lift-and-shift expensive, that changes the disposition decision for that system, which is exactly the kind of input that should arrive before the plan is fixed rather than after. Migration away from an expensive licensing model is often the point of the exercise, and we treat that as part of legacy modernization rather than as a surprise.

Nobody asked who will run it

A migration programme has a delivery team, a plan, and an end date. The estate it produces has no end date. The gap between those two facts is where projected savings go.

Cloud infrastructure operated with on-premise habits costs more than the infrastructure it replaced. The habits are reasonable ones in their original context: size for peak and leave it running, because a physical server you already bought costs the same whether it is busy or idle. Provision generously, because ordering more capacity takes six weeks. Leave environments up, because tearing them down means asking someone to rebuild them. Every one of those becomes a monthly charge in a consumption model.

The organisational version of the same gap: the operations team was not part of the design, has not been trained on the target platform, and receives it at go-live with a runbook written by people who are leaving the programme. Alerting is either absent or copied from a monitoring stack that measured different things. Cost visibility sits with the finance team a month in arrears.

The fix is not complicated, only unpopular, because it costs money before it saves any. Name the operating team at the start of the design. Give them a role in the target architecture. Train them during the programme rather than at the end of it. Put cost telemetry in place on the first migrated workload rather than the last, so the feedback loop exists while decisions are still being made.

Testing what the business does, not what the system does

Functional testing after a migration usually verifies that the application behaves as before. It rarely verifies that the process the application supports still completes end to end.

The distinction matters because business processes cross system boundaries. An order arrives through one channel, is validated by a second system, priced by a third, invoiced by a fourth, and reported in a fifth. Each of the five can pass its own tests while the chain fails, because the failure lives in a timing assumption, a batch window, or a file format that one side changed and the other tolerated by accident.

Migration test plans should be built from the process inventory rather than the application inventory: pick the ten or fifteen flows the business cannot operate without, trace each one across every system it touches, and validate the full chain against realistic volumes before cutover. This catches the class of defect that no unit test finds and that is discovered otherwise on the first business day in the new environment, under time pressure, with an audience.

The challenges are known, the ownership is not

Read the list again and a pattern shows up. None of these are unknown risks. Every organisation has someone who could name most of them within an hour of being asked. They become problems because they sit between roles: dependency discovery falls between infrastructure and application teams, licensing between procurement and delivery, the operating model between the programme and the line organisation.

A migration plan that accounts for them does not need new methodology. It needs each item to have a name attached, a date by which it is answered, and a place in the schedule before the point at which it can still change the design. That is a governance choice made in the first weeks, and it is considerably cheaper than discovering the same items in the last ones.

If you are scoping a migration and want a second reading on the dependency map, the licensing exposure or the target operating model, our cloud migration practice works on exactly these questions before the first workload moves.

Related services: Cloud Solutions, IT Consulting