ANY CLOUD → STACKIT · CHECKLIST
STACKIT migration checklist for cloud architects
A checklist is only useful when each box points at evidence. This one is organised in six phases, discovery to retirement, and every check names the file of a StackToIT run where the answer is written. The files quoted come from a run on a small AWS estate written for this page: a network, a web server, a PostgreSQL database, a bucket and a secret.
What the run writes for your checklist
Assessed by StackToIT on 4 November 2026. Left: the wave order the run computed from the dependencies between the seven resources. Right: the first lines of the check list the run wrote, ready to tick.
## Wave 1 — 4 unit(s)
| Unit | Class | Target |
|---|---|---|
| `aws_db_instance.orders` | REPLATFORM / MEDIUM | STACKIT PostgreSQL Flex |
| `aws_s3_bucket.uploads` | DIRECT / MEDIUM | STACKIT Object Storage |
| `aws_secretsmanager_secret.db` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |
| `aws_vpc.main` | RECONFIGURE / MEDIUM | STACKIT project networking / Network Area (SNA) |
## Wave 2 — 2 unit(s)
| Unit | Class | Target |
|---|---|---|
| `aws_security_group.web` | RECONFIGURE / MEDIUM | STACKIT security group |
| `aws_subnet.app` | RECONFIGURE / MEDIUM | STACKIT network |## Before each step
- [ ] `TF/stackit_network.app` · `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.Waves are a starting point
The run says it plainly: units in the same wave can move in parallel, and the order is a starting point for your wave plan, not a schedule.
Checks are generated, not generic
Each box names a step of the plan and the condition that must hold before it, for example that the variable project_id has a value.
1. Discovery
Establish what exists and how much of it the tool could see.
Make the source complete
The run reported VARIABLE_UNRESOLVED because the variable db_password had no value. Pass the variable file with --var-file before you trust any count. Check: the console summary and summary.source_inputs in assessment.json.
Read the class of every unit
Seven resources became seven units: one DIRECT, five RECONFIGURE and one REPLATFORM, none REDESIGN. The class names the type of work, it does not authorise it. Check: assessment.json, engineering/architect-report.md.
Open the not-carried list
engineering/not-carried-summary.csv counts the properties of a unit that the draft does not carry. In this run: two for the database (the password and skip_final_snapshot), one for the secret, one for the subnet. Settle each one with the owner of the unit.
Find the stateful units
migration/data-movement.md lists the database and the bucket as stateful, with the mechanism UNKNOWN and the state DECISION REQUIRED. It also lists what the source does not tell you: data size, change rate, tolerated downtime, recovery point.
2. Design
Turn open questions into recorded answers.
Answer the decision register
The console reported 6 decisions to make and 3 defaults to confirm. The files count differently: decisions.json of the same run holds 19 open records, so tick each record off in the file, not against the console figure. Examples from this run: how the database data moves, whether a public endpoint is acceptable for PostgreSQL Flex, which flavor the derived size stands for. Check: executive/decisions.md, decisions.json.
Review every change in exposure
The source database was not proven public, the STACKIT instance has its own endpoint limited by a client list. The run also flags that the subnet had no internet route while the drafted network leaves through STACKIT source NAT. Both are architecture changes you accept or redesign.
Confirm derived sizes
The draft maps db.m5.large (2 vCPU, 8 GiB) to the flavor 2.16-replica (2 vCPU, 16 GiB), the smallest replica flavor that covers it, and converts 100 GiB of storage to 108. The run calls this a proposal. Confirm it or choose another size.
Check the landing zone
migration/landing-zone-requirements.md lists what the organisation and project must provide before the first apply, and the values a person supplies.
3. Build
Prepare the target and apply the draft in the right order.
Supply the open values
Here 15 of 15 automated steps free of decisions still wait for a value: project_id, orders_access_scope, orders_allowed_cidrs and postgresflex_storage_class. Write them in review/target-values.tfvars and run again.
Name the image and machine type
The boot image is a variable a person sets, never an image id the tool guesses. The same holds for the machine type and the boot volume size of the web server.
Follow execution/terraform/apply.md
OpenTofu applies the whole draft at once and does not enforce manual steps or API calls. The file lists what to complete before apply and, where needed, a first apply of selected blocks with -target.
Decide on API opt-in
The secret is written through a STACKIT API that is not documented as generally available. The plan makes no such call until the Platform Architect answers the opt-in decision in executive/decisions.md; the console names it as the first blocker.
4. Data
Choose the mechanism, move, prove.
Pick a method per stateful unit
For the database the plan keeps two methods open: a dump restored inside the write freeze, or logical replication. On Amazon RDS, logical replication needs the static parameter rds.logical_replication set to 1 and a reboot of the source instance, so it is a change to the source. For the bucket: a copy with rclone, or the AWS CLI through a staging directory. Choose by data size, change rate and tolerated downtime.
Hand over the new database password
The source password is not copied. STACKIT generates one for the migrated user and the draft exposes it as a sensitive output. Give it to every client before cutover; the Terraform state holds it in plain text.
Plan the reconcile
Three manual reconcile steps compare source and target with the writers stopped. The checks named for the database include row counts, table checksums and sequences.
Export before you destroy
The source database sets skip_final_snapshot, and the drafted instance has no final-backup setting either. Export the data first if it has to survive.
5. Cutover
Switch on a decision, with a way back.
Write down the cutover facts yourself
The run found no DNS record set, certificate or public address to re-bind and says that this proves nothing about names and addresses outside the scanned source. List them.
Record the rollback limit
The reconcile step carries a check called rollback-limit, the point after which a rollback loses data. The owner records it before the window. Until the switch, clients still point at the source.
Close the egress decision
STACKIT creates an allow-all IPv4 egress rule on the security group that the draft does not manage, while the source allowed only the egress it listed. Decide whether to remove it after apply.
Name a go or rollback owner
The plan assigns the check of the migrated estate and the go or rollback decision to roles, among them a Migration Owner. Map the roles to people.
6. After
Close the loop and keep the record.
Verify the published folder
stacktoit verify checks the run folder against its manifest and the artefacts against each other. It is no signature and no proof that anything changed in a cloud.
Rerun after every answer
Answers go into review/inputs.yaml and review/decisions.yaml, and the next run reads them. Look for answers it reports as invalid or stale.
Keep the source until acceptance
The data-copy steps say to leave the source bucket and access untouched until the target is verified. Retirement packages for the source come last in the plan.
Journal progress
review/progress.yaml is the template for a progress journal that a later run can read with --progress.
Which file answers which question
Open these in this order when you review a run.
| Question | File | What you read there |
|---|---|---|
| Is the source complete? | console.txt, assessment.json | Source status and missing inputs |
| What is the class of each unit? | engineering/architect-report.md | Unit table with class, confidence and reasons |
| In what order do units move? | migration/technical-sequencing.md | Waves computed from dependencies |
| What must be decided? | executive/decisions.md | Decisions with options and the steps they hold |
| What is not carried over? | engineering/not-carried.csv | Properties the draft leaves out, by unit |
| What do I supply? | review/target-values.tfvars | Open variables of the draft |
| Who does what? | migration/work-packages.csv | Work packages with owner role and state |
| How does data move? | migration/data-movement.md | Stateful units, mechanism and checks |
A run is a proposal. Nothing in it is approved until your architects record the decisions.
Questions architects ask about the checklist
Does this checklist replace our own change process?
No. It gives your process evidence to work from. The run is a proposal, and every decision, approval and execution step stays with your people.
Why are so many steps marked as waiting?
Because the source does not state everything. In the demo run, steps wait for a project id, an access list, a storage class and a handful of decisions. Answering them is the work of the design phase.
Is the order of the phases fixed?
The phases follow the order of dependencies: you cannot size a flavor before you know the class, and you cannot cut over before the data method is chosen. Within a phase the order is yours.
Where do the Terraform files come from?
StackToIT writes a STACKIT Terraform draft into the terraform folder of the run for the resources it can draft. Review it with the target-platform team before any apply.
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.