AWS → STACKIT · CHECKLIST

AWS to STACKIT migration checklist

Use this list to carry an AWS estate to STACKIT without losing track. Every check names the file of the StackToIT output folder that holds the answer, so a reviewer can tick it against evidence instead of memory. Examples come from a demo estate of nine AWS units and from the published Retail Store run.

How the checklist is organised

Six phases, in the order the work happens. The file names are paths inside the output folder of an assessment.

  • Evidence, not opinion

    A check is done when the file named beside it says so, or when a person has recorded the answer in the review files. StackToIT reads and writes files and changes nothing in any cloud.

  • Sized by a real run

    The Retail Store run covers 282 Terraform resources and 44 migration units. Your estate gets its own numbers; the checks stay the same.

  • Decisions are part of the list

    Open decisions block steps of the plan. A checklist that skips them ticks boxes the plan will not honour.

Phase 1 · Discovery

CheckWhere the answer isDone when
The whole estate was read: every root module, child module and variable fileconsole.txt and assessment.json (resources scanned, migration units)The unit count matches what your team expects; missing modules are explained
Variables that decide whether a resource exists are knownconsole.txt (visibility line), assessment.json (conditional units)No unit is left conditional by a variable you can state; the Retail Store run records 41 units switched off and 8 conditional units that only a plan decides
The source passes its own checksconsole.txt (source checks)Validation ran, or you know why it did not (for example no dependency lock file)
Resources outside Terraform are listedYour inventory; the optional discover command adds read-only collectionConsole-created resources are added by hand, because an assessment only sees what is in the files

Phase 2 · Design

CheckWhere the answer isDone when
Every unit has a class and a targetassessment.json, migration/source-target.csvNo unit is unexplained; REDESIGN and MANUAL_REVIEW units have an owner
Open decisions are listed and ownedexecutive/decisions.md, decisions.json, review/decisions.yamlEvery decision that blocks a plan step has an answer or a date
Defaults the draft chose are confirmed or changedexecutive/decisions.md (defaults to confirm)Public endpoint, sizing and egress defaults each have a recorded answer
What the draft does not carry is understoodengineering/not-carried.csv, engineering/architect-report.mdEach not-carried property has a decision or an accepted loss
The landing zone is definedmigration/landing-zone-requirements.mdOrganization, project, region and network ranges are agreed

What "not carried" looks like

engineering/not-carried-summary.csv of the demo run: one row per unit with the number of properties the draft could not carry. A non-zero count is a design check, not an error.

Not-carried summaryengineering/not-carried-summary.csv
unit,type,class,confidence,counted,properties_not_carried
aws_db_instance.orders,aws_db_instance,REPLATFORM,MEDIUM,yes,3
aws_instance.app,aws_instance,RECONFIGURE,MEDIUM,yes,2
aws_s3_bucket.uploads,aws_s3_bucket,RECONFIGURE,MEDIUM,yes,1
aws_secretsmanager_secret.api_key,aws_secretsmanager_secret,RECONFIGURE,MEDIUM,yes,1
aws_subnet.app_a,aws_subnet,RECONFIGURE,MEDIUM,yes,1
aws_subnet.app_b,aws_subnet,RECONFIGURE,MEDIUM,yes,1
aws_vpc.app,aws_vpc,RECONFIGURE,MEDIUM,no,

Phase 3 · Build

CheckWhere the answer isDone when
Required services are enabled in the target project and regionterraform/README.md (enable these services first)The services the draft uses are enabled; the portal shows a disabled one as not enabled in your region
Variables without defaults have valuesreview/target-values.tfvars (the copy of target-values-template.tfvars), terraform/variables.tfproject_id, access scopes, client CIDRs, machine types and storage classes are set
The draft validates against a test projectterraform/README.md (init, validate, plan)A plan runs clean in a test project; StackToIT never runs apply
The state is treated as a secretterraform/README.md (secrets the provider writes into the state)State storage and access are decided before the first apply
Apply order and pre-steps are followedexecution/terraform/apply.mdManual steps and API calls that must come first are ticked
Opt-in API calls are decidedexecutive/decisions.md, execution/api/Each call to an API without a stated release status is allowed or refused on record

Phase 4 · Data

CheckWhere the answer isDone when
Every stateful unit has a chosen move methodmigration/data-movement.mdNo unit reads DECISION_REQUIRED
Size, change rate and downtime tolerance are statedreview/inputs.yaml (dataset size, downtime, RPO), migration/data-movement.md ("Not known" list)The unknowns the report lists are replaced with your numbers
The method was rehearsedStep "data rehearsal" in execution/manual/actions.mdThe elapsed time of each part is recorded and the freeze window is agreed from it
Secrets are copied by a personSecrets Manager steps in execution/manual/actions.mdValues are in STACKIT Secrets Manager; the draft never holds them
The comparison checks are agreedmigration/data-movement-plan.json (checks of each asset)Counts, lists or checksums are named per store, with a GO or NO-GO owner

The data table and the pre-step checks

Left: migration/data-movement.md. Every unit reads DECISION_REQUIRED and the data class, RPO and downtime are NOT_PROVIDED until you state them. Right: the first lines of execution/verify/checks.md, a tickable list generated from the plan.

Data movement tablemigration/data-movement.md
| Unit | Source service | Target service | Application | Mechanism | State | Data class | RPO | Downtime tolerance |
|---|---|---|---|---|---|---|---|---|
| aws_db_instance.orders | aws_db_instance | STACKIT PostgreSQL Flex |  | UNKNOWN | DECISION_REQUIRED | NOT_PROVIDED | NOT_PROVIDED | NOT_PROVIDED |
| aws_s3_bucket.uploads | aws_s3_bucket | STACKIT Object Storage |  | UNKNOWN | DECISION_REQUIRED | NOT_PROVIDED | NOT_PROVIDED | NOT_PROVIDED |
Checks before each stepexecution/verify/checks.md
## Before each step

- [ ] `TF/stackit_network.app_a` · `variable-supplied` `variable=project_id` — The variable `project_id` has a value.
- [ ] `TF/stackit_network.app_b` · `variable-supplied` `variable=project_id` — The variable `project_id` has a value.
- [ ] `TF/stackit_secretsmanager_instance.migrated_secrets` · `variable-supplied` `variable=project_id` — The variable `project_id` has a value.
- [ ] `TF/stackit_secretsmanager_user.migration` · `variable-supplied` `variable=project_id` — The variable `project_id` has a value.

Phase 5 · Cutover

CheckWhere the answer isDone when
The applications that use each store are listedCutover steps in execution/manual/actions.mdThe plan does not read which applications use a store; their owners list them
The window and the freeze are agreedWrite-freeze steps; the maintenance window input in review/inputs.yamlA window is stated by the owner; the plan invents none
DNS has a lowered TTL and a rollbackmigration/technical-sequencing.md (zone delegation steps)TTL lowered and expired, answers verified at the target name servers
The rollback decision step has an ownerRollback decision step in execution/manual/actions.mdA named owner will record GO or ROLLBACK
See the cutover and rollback runbook for the ordered stepsCutover and rollback runbookEvery step has an owner, a check and a way back

Phase 6 · After the cutover

CheckWhere the answer isDone when
Progress is recordedreview/progress.yamlEach step is DONE, FAILED or WAIVED with an owner and a date
Restore is provenRestore check step for each databaseA point-in-time clone was read and compared before the GO
The source is retired in orderDecommission steps in execution/manual/actions.mdRetirement started only after GO; final backups kept for the period you decided
The result is archived unchangedOutput folder and its manifest.jsonThe folder verifies with the verify command before it is shared or archived

Where you record progress

review/progress.yaml starts from progress-template.yaml. Each entry ties to the step by a hash; if a later run changes the step, your entry is shown as stale rather than silently carried over.

Progress journalprogress-template.yaml
entries:

  # MANUAL critical-semantic - aws_subnet.app_a
  - action_id: "MAN/semantic/aws_subnet.app_a/availability-zone"
    contract_sha256: "sha256:466db94bafa1a6993c03688825aff955665d3be7fa1f3d4387e6c6a0c7d4ac72"
    state: NOT_STARTED

  # MANUAL critical-semantic - aws_subnet.app_a
  - action_id: "MAN/semantic/aws_subnet.app_a/effective-route-table"

Questions teams ask

Can the checklist be ticked from the report alone?

Only for the design phases. Build, data, cutover and after need work in your environment; the files tell you what to do and what counts as done, and you record the result in the review files.

Do I need a full AWS inventory first?

The assessment reads Terraform. For comparison with the live account the discover command collects read-only inventory with your local AWS credentials, and the assessment itself never connects to AWS.

Where do managed databases and buckets show their risks?

In the data movement files and the not-carried list: engine versions, public or private endpoints, bucket settings that go through an API instead of Terraform, and encryption statements that are unknown.

Is every box mandatory?

No. WAIVED exists in the progress journal for a reason, but a waiver needs a note, so the omission stays visible.

Sources

Your next move: STACKIT.

Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.