The Challenge

When DataFlow Solutions asked me to migrate their entire infrastructure — 80 VMware virtual machines — to AWS, the requirement was clear: zero downtime. No maintenance windows. No service interruptions. Just a seamless transition that users wouldn't even notice.

Here's exactly how we did it over 6 months.

Phase 1: Assessment (Weeks 1–2)

Before touching a single server, we ran a complete inventory:

# Export VMware VM inventory
govc ls -json /datacenter/vm | jq '.elements[].Object.Config | {name: .Name, cpu: .Hardware.NumCPU, mem: .Hardware.MemoryMB, os: .GuestFullName}'

We categorized every VM into three buckets:

  • Lift-and-shift — stateless apps that move as-is
  • Replatform — apps that benefit from managed services (RDS, ElastiCache)
  • Refactor — legacy apps that need rearchitecting

Phase 2: Terraform Infrastructure

We defined all AWS infrastructure as code:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "dataflow-prod"
  cidr = "10.0.0.0/16"

  azs             = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = true
  single_nat_gateway = false  # HA setup
}

resource "aws_instance" "app_server" {
  ami           = data.aws_ami.rhel9.id
  instance_type = "t3.large"
  subnet_id     = module.vpc.private_subnets[0]

  tags = { Name = "app-server-01", Environment = "production" }
}

Phase 3: The Blue/Green Strategy

This was the key to zero downtime. We ran both environments in parallel:

  1. Stand up full AWS environment (green)
  2. Set up real-time data replication from on-prem to AWS
  3. Test green environment thoroughly
  4. Switch DNS with low TTL (60 seconds)
  5. Monitor for 48 hours
  6. Decommission on-prem (blue)

Phase 4: Data Replication

# Continuous MySQL replication to RDS
mysqldump --single-transaction --master-data=2 production | 
  ssh aws-bastion "mysql -h rds.endpoint.amazonaws.com production"

# Set up replication
mysql -h rds.endpoint -e "
  CHANGE MASTER TO
    MASTER_HOST='on-prem-mysql.internal',
    MASTER_USER='replication',
    MASTER_PASSWORD='${REPL_PASS}',
    MASTER_LOG_FILE='mysql-bin.000042',
    MASTER_LOG_POS=4;
  START SLAVE;"

Results

After 6 months of careful execution:

  • Zero downtime — not a single user-facing outage
  • 40% cost reduction — from $18k/month to $10.8k/month
  • 60% better performance — faster instances, better I/O
  • Full IaC — entire infrastructure in Terraform

Lessons Learned

The biggest lesson: test your rollback plan as carefully as your migration plan. We had a fully tested rollback procedure for every phase. We never needed it, but knowing it worked gave us the confidence to proceed.