Level Up

How to Turn an AWS Migration Assessment into Terraform

Level Up Team

A migration assessment that cannot become infrastructure-as-code is still a document.

Terraform should not invent the target architecture. It should render the parts of the assessment that are already decided and declarative.

That is the contract behind Level Up's AWS migration assessment: evidence in, backlog out, Terraform and Ansible as execution surfaces.

What belongs in Terraform

From an assessment record, Terraform is the right tool when the target is an AWS resource graph:

  • Accounts, VPCs, subnets, routing
  • IAM, security groups, SSM
  • RDS, FSx, ECS, load balancers
  • CloudWatch, backup vaults, Transfer Family

Ansible remains the right tool for OS configuration, application cutover, validation, and anything that is a procedure rather than a resource. See the Terraform + Ansible split.

Start from the assessment record, not a blank module

# excerpt from an assessment workload
id: wms
disposition: replatform
target:
  compute: ecs
  data:
    service: rds-postgresql
    engine_version: "15"
    storage_gb: 380
    multi_az: true
constraints:
  extensions_reviewed: true
module "wms_db" {
  source = "./modules/rds-postgres"

  identifier     = "wms"
  engine_version = var.assessment.wms.target.data.engine_version
  allocated_gb   = var.assessment.wms.target.data.storage_gb
  multi_az       = var.assessment.wms.target.data.multi_az

  subnet_ids = module.landing_zone.app_subnets
  tags = {
    workload    = "wms"
    disposition = "replatform"
    wave        = "3"
  }
}

The module is reusable. The inputs come from the assessment. If the assessment changes — storage, engine, wave — Terraform is regenerated from the same system of record.

Generate candidates, not a surprise repo

An assessment should emit a candidate list, not a finished production estate:

T-001  terraform  landing zone VPC and plant connectivity
T-041  terraform  RDS PostgreSQL for WMS
T-072  terraform  ERP VPC, RDS, and security groups

Engineers accept, reject, or split those candidates. That is the human-decision step in fact → inference → recommendation → human decision.

Look at the tagged tasks in the example backlog.

Keep secrets and procedures out of state

Do not stuff cutover runbooks, SQL validation, or one-time data copies into Terraform. Those are Ansible (or a pipeline) for a reason.

- name: Validate WMS against RDS
  hosts: wms_app
  tasks:
    - name: Check application health
      ansible.builtin.uri:
        url: "https://wms.internal/health"
        status_code: 200

Reciprocal loop

Website and repository should work as a pair: inspect the code, run an example, then decide whether you want Level Up to operate the assessment and execute the migration.

Start at the assessment page, the Acme example, or request an assessment.