AWS → STACKIT · RUNBOOK
AWS to STACKIT cutover and rollback runbook
A cutover is a sequence of small, reversible steps followed by one irreversible one. This runbook orders the steps the way StackToIT orders them for a demo estate (a PostgreSQL database, a bucket, a server and a DNS zone), gives each an owner, a check and a way back, and marks the point after which the way back is a rebuild from backups.
How to use this runbook
The order comes from the run's execution plan, the owners and rollback lines from the manual steps it writes (execution/manual/actions.md). Rows marked practice are general good practice that the run does not write.
Source of the order
Dependencies set the waves; the cutover steps carry "after" links, so readiness follows the last data reconcile, the switches follow readiness and the rollback decision follows every check.
Nothing runs by itself
StackToIT creates, changes and deletes nothing. Each step is done by a person, by OpenTofu or by a script your team runs.
No timings
The plan states no maintenance window and invents none. Take durations from your rehearsal, not from a table.
The build order: three waves
From migration/technical-sequencing.md of the demo run: nine units in three waves. Units of one wave can move in parallel; the file calls it a starting point for your wave plan, not a schedule.
## Wave 1 — 4 unit(s)
| Unit | Class | Target |
|---|---|---|
| `aws_route53_zone.main` | DIRECT / MEDIUM | STACKIT DNS |
| `aws_s3_bucket.uploads` | RECONFIGURE / MEDIUM | STACKIT Object Storage |
| `aws_secretsmanager_secret.api_key` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |
| `aws_vpc.app` | RECONFIGURE / MEDIUM | STACKIT project networking / Network Area (SNA) |
## Wave 2 — 3 unit(s)
| Unit | Class | Target |
|---|---|---|
| `aws_security_group.db` | RECONFIGURE / MEDIUM | STACKIT security group |
| `aws_subnet.app_a` | RECONFIGURE / MEDIUM | STACKIT network |
| `aws_subnet.app_b` | RECONFIGURE / MEDIUM | STACKIT network |
## Wave 3 — 2 unit(s)
| Unit | Class | Target |
|---|---|---|
| `aws_db_instance.orders` | REPLATFORM / MEDIUM | STACKIT PostgreSQL Flex |
| `aws_instance.app` | RECONFIGURE / MEDIUM | STACKIT Compute Engine |Phase 1 · Before the window
| Step | Owner · done when | Rollback |
|---|---|---|
| Answer the open decisions: data movement method for the database and for the bucket, the opt-in for the S3 API calls, the boot image of the server, the sizing and endpoint defaults | Architects · the steps that wait for a decision are freed (executive/decisions.md; the demo has 6 decisions, 5 of which hold steps) | Nothing changed yet |
| Fill the variables (project_id, access scope, client CIDRs, storage class, image, machine type), complete the pre-steps of execution/terraform/apply.md, then apply the reviewed Terraform (OpenTofu applies all its steps in one apply) | Platform team · every item of execution/verify/checks.md ticked | Destroy the new STACKIT resources; the source is untouched (practice) |
| Lower the TTL of the zone and of its delegation, then wait the old TTL (the demo zone's largest TTL is 300 s) | Network Architect · the old TTL has passed | Raise the TTL again (practice) |
| Query each record at a STACKIT name server directly and compare with Route 53 | Network Architect · answers match, except where the value is an AWS endpoint | Do not touch the registrar until they match |
| Data preflight and rehearsal for the database and for the bucket; initial copy and a replication watch where the method has one | Data Architect · the elapsed time of each part is recorded and the freeze window is agreed from it | Delete the scratch instance; the source is unchanged |
| Restore check: clone the new PostgreSQL Flex instance to a point in time, read it, compare, record the duration, delete the clone | Storage Architect · clone agrees with the source; AWS backup retention date recorded | A check changes nothing; delete the scratch resources |
| Decide now whether writes made on the target after the switch are copied back or accepted as lost | Migration Owner · decision recorded before the window, not in the incident | Not applicable |
Phase 2 · Freeze and final copy
| Step | Owner · done when | Rollback |
|---|---|---|
| Cutover readiness: confirm every workload step and data move is done before the first switch | Migration Owner · each step it follows is recorded as done | A confirmation changes nothing |
| Write freeze: list who writes, record every client's connection settings, stop the services, jobs and migrations that write | Migration Owner · no client writes to the source | Start the writers again against the source: nothing was changed |
| Final copy: dump and restore inside the freeze, or wait for zero replication lag, copy the sequences and disable the subscription; copy the last objects of the bucket | Data Architect · lag was 0, target sequences are not lower than the source's | The slot is still on the source and the source untouched: put the writers back |
| Reconcile: row counts, checksums, sequences and one query the application runs; object counts and key lists for the bucket; record GO or NO-GO | Data Architect · numbers equal on both sides | On NO-GO take the rollback without switching anything |
Phase 3 · The switch
| Step | Owner · done when | Rollback |
|---|---|---|
| Switch the connection of the applications that use the database: host, port, database name and credentials | Data Architect · every application connects to PostgreSQL Flex and the AWS instance receives no reads or writes | Point the configuration back; what was written to the target meanwhile is not in AWS |
| Switch the applications that use the bucket: endpoint, bucket name and access keys | Storage Architect · applications use the STACKIT bucket, the AWS bucket sees no requests | Point the configuration back to the AWS bucket |
| Traffic switch for the server: move clients from its AWS address to its STACKIT address | Network Architect · requests reach the STACKIT address, the AWS address receives none | Change the clients back; the AWS resources stay until the GO |
| Delegation change of the zone: replace the Route 53 name servers with those STACKIT shows, at the registrar or the parent zone | Network Architect · the parent answers the STACKIT NS records and a resolver asked after one parent NS TTL agrees | Set the NS records back to Route 53; keep the STACKIT zone for at least one parent NS TTL |
| Cutover completion: confirm every switch is recorded as done | Migration Owner · the owner records that the cutover is complete | A confirmation changes nothing |
The two steps that carry the rollback
Verbatim line ranges from execution/manual/actions.md of the demo run: the risk and the rollback of the delegation change, then the head and the rollback of the rollback decision step. The long dependency and state lines between them are left out.
- Risk: while resolvers hold the old delegation (one parent NS TTL) some answer from Route 53 and some from STACKIT: a record changed in one zone and not in the other is seen by part of the clients only, so both zones hold the same records until the TTL has passed
- Rollback (manual): set the NS records at the registrar (or the parent zone) back to the Route 53 name servers; resolvers that hold the STACKIT delegation keep it for one parent NS TTL, so the STACKIT zone stays in service for at least that long after the rollback, and the Route 53 zone is retired only after the GO recorded at the rollback decision step#### The rollback decision step (`MAN/verify/rollback-decision`)
- Phase: Verification
- What: Decide GO or ROLLBACK for the migration once every check of the verification is done: GO lets the source resources be retired, ROLLBACK reverts the cutover and keeps AWS serving
- Why: reverting the cutover is a change of addresses only while the AWS resources exist; after the first decommission step the way back is a rebuild from backups
- Who: Migration Owner
- When: after every check of the verification- Risk: the decision point follows every check of the verification (each is also an action-complete precondition); the retirement steps depend on it, and through it on the checks
- Rollback (manual): on ROLLBACK, revert each cutover step as its rollback says (the traffic switch of aws_instance.app, the delegation change of the hosted zone of aws_route53_zone.main, the switch of the applications that use aws_s3_bucket.uploads, the switch of the applications that use aws_db_instance.orders) and start no decommission step; on GO nothing is revertedPhase 4 and 5 · Verify, decide, retire
| Step | Owner · done when | Rollback |
|---|---|---|
| Endpoint check right after the traffic switch, then the data checks for the database and the bucket: counts agree, the application reads migrated records, a test write is read back | Network, Data and Storage Architects · status and content match what the AWS address gave | Checks change nothing; remove the test record they wrote |
| Rollback decision: record GO or ROLLBACK with the date and the result of each check | Migration Owner · decision recorded | On ROLLBACK revert each switch as its own rollback says and start no retirement step |
| Clean up the data move: drop the subscription and publication, remove the move host from the access list, delete dump files, rotate the credentials, keep a final snapshot of the source; setting rds.logical_replication back means a reboot, a second outage of the source if you keep it | Data Architect · no slot, subscription, publication or dump file is left and the move host is out of the access list | None: after the cleanup the way back is the final snapshot of the source |
| Retire each AWS resource on its own (database, secret, server, bucket, zone, security group, subnets, network), each only after the resources that depend on it are gone | Each resource owner · the resource no longer exists in the AWS account and its charges stop on the bill | Impossible for the database: only the final backup restores its data, into a new resource |
| Turn on instance protection for critical production instances of PostgreSQL Flex (practice; STACKIT's release notes advise it, because deleting an instance without it loses the data at once) | Data Architect · protection enabled | Disable it deliberately when you need to delete |
The DNS draft behind the delegation step
The STACKIT DNS zone and record set the demo run wrote (terraform/dns.tf, without comments). The record keeps the 300 s TTL of the source.
resource "stackit_dns_zone" "main" {
project_id = var.project_id
name = "orders.example.com"
dns_name = "orders.example.com"
}
resource "stackit_dns_record_set" "app" {
project_id = var.project_id
zone_id = stackit_dns_zone.main.zone_id
name = "www.orders.example.com"
type = "A"
records = ["203.0.113.10"]
ttl = 300
}Rules for the rollback
Where the way back ends, and what you give up on the way.
Keep the source whole until the GO
The plan never makes the source read-only or changes it after the freeze, so a rollback is only configuration put back. Delete nothing in AWS before the rollback decision is GO.
Writes after the switch
Whatever the applications wrote to STACKIT after the switch is not in AWS. Copy it back with a separately rehearsed method or accept it as lost, and decide before the window.
DNS needs patience
Resolvers keep the old delegation for one parent NS TTL after a change, so both zones must hold the same records for that long. The TTL of the delegation at the registrar is not in the source.
DNSSEC (practice)
AWS documents for the opposite direction that a domain cannot be signed by two providers at once and the DS record must be removed first. If your zone is signed, plan the DS record in both directions.
The point of no return
After the first retirement step the way back is a rebuild from backups. That is why the decision step is separate and carries a date and the result of every check.
Questions teams ask
How long should the maintenance window be?
The plan states no window and invents none. Take the copy times from your rehearsal, add the comparison and the switch, and agree the window with the application owners.
Can StackToIT run the cutover for us?
No. It writes the steps, owners and checks. An executor that would carry out the plan step by step is described in the package as designed and not implemented.
Do we switch DNS first or the data first?
The plan orders the data reconcile, then readiness, then the switches. The delegation change waits for the STACKIT zone to hold every record and for the lowered TTL to have passed.
What if the reconcile fails?
Take the rollback without switching anything. The clients still point at the source, which is current up to the freeze.
Sources
- Making Route 53 the DNS service for a domain that is in use (AWS documentation, the reverse direction)
- STACKIT PostgreSQL Flex (STACKIT documentation)
- STACKIT Object Storage (STACKIT documentation)
- Backup and clone of PostgreSQL Flex (STACKIT documentation)
- STACKIT DNS: manage DNS zones (zone delegation)
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.