Migrating hundreds of legacy VM applications to AWS works when you run it as a production line rather than hundreds of one-off projects: inventory and classify every app, decide upgrade or rebuild per app, and split the estate into blocks owned by small teams. A shared application skeleton, tested cutover and rollback steps, and runbooks any team can follow keep quality steady as volume grows.
Start with an inventory that shows what each app really needs
Before anyone touches AWS, list every application running on the legacy VMs and record the facts that drive migration effort. A shared spreadsheet is enough at first. What matters is that every app has a row, an owner and the same columns.
Then classify each app into a small number of tracks, such as upgrade, rebuild and retire. Teams can then plan by track instead of debating each app from scratch.
- Runtime and framework version, flagging anything past end of life
- Databases, file shares and scheduled jobs the app depends on
- Inbound and outbound integrations, including hard-coded hostnames and IP addresses
- Authentication method and any secrets stored on the VM
- Business owner, usage level and acceptable downtime window
Decide upgrade or rebuild per app, not once for the whole program
No single strategy fits hundreds of apps. Some only need a framework upgrade, externalized configuration and a new deployment target. Others carry so much dead code or tangled structure that rebuilding on a clean base is faster than repairing them.
Make the call with written criteria so different teams reach the same answer. A useful rule: if landing the app on the standard skeleton means rewriting most of its controllers and data access anyway, rebuild it. If the business logic ports mostly intact, upgrade it.
The Crédit Agricole program, which moved 600+ internal applications from legacy VMs to AWS, used both paths. Apps were rebuilt on the bank's internal CodeIgniter skeleton, some upgraded and some rebuilt from scratch.
- Upgrade when the code is readable, its behavior is clear and the framework gap is small
- Rebuild when business logic is mixed into presentation everywhere or the app depends on removed language features
- Retire when usage is near zero and the business owner agrees, because the cheapest migration is the one you skip
Split the estate into blocks and give each block to one team
At this scale, a single central team becomes the bottleneck. A block-split model assigns a batch of related apps to one small team that owns them from analysis to cutover.
Group blocks by shared dependencies, not alphabetically. Apps that share a database or call each other should move together, or the same integration work gets repeated across teams.
Blocks also make progress measurable. Every team reports the same states for each app, such as analyzed, migrated, tested, cut over and decommissioned, and the program board is the sum of those states. The Crédit Agricole program ran this way, and SDK Enterprises delivered 50+ of its application migrations as part of the program team.
Build one standard skeleton and make every app land on it
A standard application skeleton is what turns hundreds of migrations into a repeatable process. It fixes the decisions that should not be made again for every app: directory layout, configuration from environment variables, logging format, health checks, authentication hooks and the deployment pipeline.
Each migrated app then differs only in its business logic. Reviewers know where to look, operations teams get consistent logs and alarms, and a fix to the skeleton reaches every app built on it.
Keep the skeleton small and versioned. If it grows into a framework of its own, teams will start working around it.
Plan cutover and rollback before the first migration
Every app needs a cutover plan that states how traffic moves, how data moves and how to go back. Decide these before the first app moves. Improvising a rollback during an incident is how migration programs lose the business's trust.
- Freeze window: agree with the business owner when changes stop on the old VM
- Data sync: migrate data in advance, then run a final delta sync during the cutover window
- Traffic switch: change DNS or load balancer routing, with low DNS TTLs set days in advance
- Smoke tests: a short scripted check of login, key screens and integrations right after the switch
- Rollback trigger: a named person and written conditions for switching back
- Old VM kept: stop it but do not delete it until the app has run cleanly on AWS for an agreed period
Write runbooks that any team can follow on day one
A runbook is the checklist for one repeatable operation: preparing an app, cutting it over, rolling it back, decommissioning the VM. Write each one once, test it on the first few apps, and update it every time something surprises a team.
Good runbooks name commands, owners and expected results, not intentions. Check that the app works is not a step. Log in as the test user and confirm the dashboard loads account data is.
Runbooks are also how engineers who join mid-program become productive quickly. A specialist arriving in week six should be able to cut over an app by following the documents after one paired session.
Where an outside team fits in a large migration
Large programs often need extra capacity for a defined period without handing over control. We take on migration blocks within larger programs, working on the client's skeleton, runbooks and tooling, with our engineers and vetted freelance specialists under one contract.
Key takeaways
- Inventory and classify every app before migrating any of them, so the work can be planned by track.
- Choose upgrade, rebuild or retire per app with written criteria that every team applies the same way.
- Split the estate into blocks of related apps, each owned end to end by one small team.
- A small, versioned application skeleton makes hundreds of migrations consistent and reviewable.
- Never cut over an app without a tested rollback path and the old VM still available.
FAQ
How long does it take to migrate hundreds of applications to AWS?
It depends on the number of apps, the share that need a rebuild, the number of parallel teams and the cutover windows the business accepts. Estimate after classification: time a few apps from each track, multiply by the size of each track and divide by team capacity.
Should we lift and shift legacy apps first and modernize later?
Lift and shift is fastest when an app already runs on a supported runtime and the goal is to leave a data center. For apps on end-of-life runtimes, moving them unchanged carries the old risks onto the new platform, so upgrading or rebuilding during the move is often cheaper overall.
What is a block-split migration?
A block-split migration divides a large application estate into batches of related apps and assigns each batch to one team that owns it from analysis to cutover. It removes the central bottleneck and makes progress easy to track across many teams.