The reliable way to migrate servers to AWS is block-level replication with AWS Application Migration Service (MGN): install an agent on each source server, let it replicate continuously into a staging area, launch test instances until the application works, then cut over during a short maintenance window while the source keeps running as your rollback. The migration itself is rarely the hard part — the hard part is the inventory and dependency work you do before installing the first agent.
What’s happening
MGN copies every disk of a source server, block by block, into low-cost staging resources in your AWS account, and keeps the copy in sync continuously. When you launch a test or cutover instance, MGN converts that replica into a native EC2 instance — injecting drivers, adjusting boot configuration — using settings you define in a launch template. Because replication is continuous, the data on the migrated instance is current to within seconds of the source at the moment you cut over, and because the source server is untouched, rollback means turning the old machine back on. The service documentation at https://docs.aws.amazon.com/mgn/ covers agent requirements and supported operating systems; most Windows Server and mainstream Linux versions from the last decade are fine.
The model has real limits worth knowing up front. Databases replicate correctly at the block level, but a busy database is better moved with its own tooling (native replication, or AWS DMS) so you can cut over with near-zero data loss instead of a stop-the-writes window. Domain controllers should never be block-replicated into a running duplicate — build fresh ones. And anything with hardware dongles, static licensing, or multicast networking needs a plan of its own.
What to check first
- Network path and bandwidth. Replication traffic flows from each source server to the staging subnet over TCP 1500. Initial sync of a few terabytes over a small office uplink can take days — do the arithmetic before promising dates.
- OS support and boot mode. Confirm each source OS is on the MGN supported list, and note BIOS vs UEFI — surprises here show up as instances that replicate fine and refuse to boot.
- Dependencies mapped. Which servers must move together in one wave. An app server cut over without its database is a long night.
- Target sizing. Source utilization, not source specs, drives instance choice. A server bought with 64 GB of RAM that uses 6 GB should not become an r-family instance.
- Landing zone ready. VPC with subnets across two availability zones, security groups drafted, IAM in order — see multi-AZ subnet design before you place anything.
How to verify
Once agents are installed, replication state is the thing to watch. In the console: AWS Application Migration Service > Source servers, where each server shows a lifecycle state and data-replication status. From the CLI:
# Replication health for every source server
aws mgn describe-source-servers \
--query 'items[].[sourceServerID,sourceProperties.identificationHints.hostname,dataReplicationInfo.dataReplicationState,lifeCycle.state]' \
--output table
# Detail on one lagging server: which disks, how far behind
aws mgn describe-source-servers \
--filters sourceServerIDs=s-1234567890abcdef0 \
--query 'items[0].dataReplicationInfo'
Healthy servers show CONTINUOUS replication. STALLED almost always means the source cannot reach the staging area (firewall, proxy) or the staging subnet has a problem. After launching a test instance, verify it the way a user would — log in, start the application, run a transaction — not just by seeing it pass EC2 status checks:
aws ec2 describe-instance-status \
--instance-ids i-0abc123def456789a \
--query 'InstanceStatuses[0].[InstanceStatus.Status,SystemStatus.Status]'
The runbook
- Build the inventory and the waves. Hostname, OS, role, owner, dependencies, data size, and a disposition for each server. Group servers that must move together into waves; put a low-risk internal server in wave one.
- Prepare the landing zone. VPC and subnets, security groups translated from current firewall rules (translated, not “allow all until it works”), and instance roles per IAM instance profile practice. Lower DNS TTLs on records you will repoint to 300 seconds now, not on cutover day.
- Install agents and let replication reach steady state. Deploy the MGN agent wave by wave. Watch initial sync complete and confirm every server sits at
CONTINUOUSfor at least a day before scheduling anything. - Launch test instances and actually test. Boot each server in an isolated test subnet. Application starts, services talk to each other, logins work, scheduled jobs fire. Fix launch template problems now — instance type, subnet, private IP, tenancy. Iterate until a test cycle is boring.
- Rehearse the cutover on paper. A written sequence with times, owners, and a go/no-go point: stop application writes, confirm replication lag is zero, launch cutover instances, repoint DNS or the load balancer, validate, decide.
- Cut over. Execute the sequence during the agreed window. The source servers stay powered off but intact — they are the rollback. Keep them that way until the business signs off, typically one to two weeks.
- Finalize and clean up. Mark servers complete in MGN so staging resources are released, remove agents, decommission sources on schedule, and turn on backups and alarms for the new instances before you call it done.
When this is the wrong move
Block replication is the right default for servers, but not for everything on them. If the real asset is a database, replicate the database with database tooling and rebuild the host. If an application is three years from end-of-life and barely used, the honest move is retirement, not migration. And if the server exists only to run something AWS offers as a managed service — file shares, a message queue, a build runner — replatforming directly is usually less total work than migrating and then re-doing it later.
Common mistakes
- Cutting over from a replica that was never test-launched. The first boot of a converted instance is where driver and boot-mode problems appear; discover them in a test window, not the cutover window.
- Sizing targets from source hardware specs. This is how a modest server room becomes a surprising AWS bill in month one.
- Forgetting the ecosystem around the server. Monitoring agents, backup jobs, printer mappings, hard-coded IPs in other systems — the server moves and something three hops away breaks.
- Destroying the rollback too early. Wiping or repurposing source hardware in week one, before slow-moving problems (month-end jobs, monthly reports) have had a chance to surface.
Prevention
- Keep the inventory spreadsheet current through the whole project; it is the single source of truth for wave planning.
- Require a successful test-instance validation, signed off by the application owner, before any cutover is scheduled.
- Script the cutover checks — DNS answer, service ports, one application transaction — so the 2 a.m. validation is not done from memory.
- Set a calendar date to decommission sources and release MGN staging resources; forgotten staging volumes bill quietly forever.
- Put CloudWatch alarms and a backup plan on migrated instances in the same week they go live, not “later.”
A server migration executed this way is an anticlimax: the interesting work happened weeks earlier in inventory, testing, and rehearsal. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.