# Migration plan draft — default

> PROPOSAL — generated by StackToIT Assess. Architect review required before any decision.

Run `f6267c3f-2848-4aa5-89df-5fee8b15b3b9` · source digest `sha256:812c5ae3f6cc8530163abbf5b6fbe305ed3b363c4886ec6b87623db857ea0c70`

Waves are computed from resource dependencies: a unit moves only after every unit it depends on. Units in the same wave can move in parallel. This is a starting point for the architect's wave plan, not a schedule.

## Prerequisites — resolve before planning

These units are not wave members: their source is not resolved, so what exists in the source (or how many of it) is not established. Resolve each one, scan again, and only then plan around it. The wave numbers below are the dependency order of the units that are wave members (a prerequisite holds no wave, so it orders nothing); a unit that depends on a prerequisite is listed in its wave, and its dependency is open until the prerequisite is resolved — its `open_dependencies` in assessment.json name it. Resolving a prerequisite can move the units that depend on it to a later wave.

| Cause | Why it is open | Remedy | Units |
|---:|---|---|---:|
| 1 | count/for_each not known statically — 0–1 instances (decided by `module.vpc.data.aws_availability_zones.available`); POSSIBLE_SOURCE_ERROR: `slice(…, 3)` fails in Terraform and OpenTofu when the list has fewer than 3 elements (the source proves none), so the count is not exact | plan read of the data source — see engineering/architect-report.md, Uncertainty by cause | 3 |
| 2 | count/for_each not known statically — 0–3 instances (decided by `module.vpc.data.aws_availability_zones.available`); POSSIBLE_SOURCE_ERROR: `slice(…, 3)` fails in Terraform and OpenTofu when the list has fewer than 3 elements (the source proves none), so the count is not exact | plan read of the data source — see engineering/architect-report.md, Uncertainty by cause | 2 |

| Unit | Cause | Class | Units that depend on it |
|---|---:|---|---:|
| `module.vpc.module.vpc.aws_internet_gateway.this` | 1 | RECONFIGURE / MEDIUM | 3 |
| `module.vpc.module.vpc.aws_route_table.private` | 1 | RECONFIGURE / LOW | 0 |
| `module.vpc.module.vpc.aws_route_table.public` | 1 | RECONFIGURE / MEDIUM | 0 |
| `module.vpc.module.vpc.aws_subnet.private` | 2 | RECONFIGURE / MEDIUM | 11 |
| `module.vpc.module.vpc.aws_subnet.public` | 2 | RECONFIGURE / MEDIUM | 3 |

## Modules across the waves

The waves below order units, not modules: a module's units are placed by their own dependencies, so a module can spread over several waves.

- `module.dependencies` (../../lib/dependencies) — 11 unit(s) in waves 1, 3, 4 — after `module.retail_app_ecs`, `module.vpc`
- `module.retail_app_ecs` (../../lib/ecs) — 30 unit(s) in waves 1, 2, 3, 5, 6, 7, 8, 9 — after `module.dependencies`, `module.vpc`
- `module.vpc` (../../lib/vpc) — 3 unit(s) in waves 1, 2

## Wave 1 — 9 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.dependencies.module.dynamodb_carts.aws_dynamodb_table.this` | `module.dependencies.module.dynamodb_carts` | REDESIGN / MEDIUM | STACKIT MongoDB Flex (alternative — data-model redesign; PostgreSQL Flex JSONB is the other option) |
| `module.retail_app_ecs.aws_cloudwatch_log_group.ecs_tasks` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT Logs |
| `module.retail_app_ecs.aws_ecs_cluster.cluster` | `module.retail_app_ecs` | REPLATFORM / MEDIUM | STACKIT Kubernetes Engine (SKE) |
| `module.retail_app_ecs.aws_kms_key.cmk` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT KMS |
| `module.retail_app_ecs.module.carts_service.aws_iam_role.task_execution_role` | `module.retail_app_ecs.module.carts_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.retail_app_ecs.module.checkout_service.aws_iam_role.task_execution_role` | `module.retail_app_ecs.module.checkout_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.retail_app_ecs.module.ui_service.aws_iam_role.task_execution_role` | `module.retail_app_ecs.module.ui_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.vpc.module.vpc.aws_eip.nat` | `module.vpc.module.vpc` | RECONFIGURE / MEDIUM | implicit (belongs to the NAT gateway) |
| `module.vpc.module.vpc.aws_vpc.this` | `module.vpc.module.vpc` | RECONFIGURE / MEDIUM | STACKIT project networking / Network Area (SNA) |

## Wave 2 — 14 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.aws_secretsmanager_secret.catalog_opensearch` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |
| `module.retail_app_ecs.module.alb.aws_security_group.this` | `module.retail_app_ecs.module.alb` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.alb_sg.aws_security_group.this_name_prefix` | `module.retail_app_ecs.module.alb_sg` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.carts_service.aws_iam_role.task_role` | `module.retail_app_ecs.module.carts_service` | RECONFIGURE / LOW | STACKIT service account for the workload |
| `module.retail_app_ecs.module.carts_service.aws_security_group.this` | `module.retail_app_ecs.module.carts_service` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.catalog_service.aws_iam_role.task_role` | `module.retail_app_ecs.module.catalog_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.retail_app_ecs.module.catalog_service.aws_security_group.this` | `module.retail_app_ecs.module.catalog_service` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.checkout_service.aws_iam_role.task_role` | `module.retail_app_ecs.module.checkout_service` | RECONFIGURE / LOW | STACKIT service account for the workload |
| `module.retail_app_ecs.module.checkout_service.aws_security_group.this` | `module.retail_app_ecs.module.checkout_service` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.orders_service.aws_iam_role.task_role` | `module.retail_app_ecs.module.orders_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.retail_app_ecs.module.orders_service.aws_security_group.this` | `module.retail_app_ecs.module.orders_service` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.retail_app_ecs.module.ui_service.aws_iam_role.task_role` | `module.retail_app_ecs.module.ui_service` | RECONFIGURE / MEDIUM | STACKIT service account for the workload |
| `module.retail_app_ecs.module.ui_service.aws_security_group.this` | `module.retail_app_ecs.module.ui_service` | RECONFIGURE / MEDIUM | STACKIT security group |
| `module.vpc.module.vpc.aws_nat_gateway.this` | `module.vpc.module.vpc` | RECONFIGURE / MEDIUM | implicit outbound (STACKIT network) |

## Wave 3 — 7 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.dependencies.aws_security_group.catalog_opensearch_sg` | `module.dependencies` | RECONFIGURE / MEDIUM | not written by this draft (stackit_security_group, stackit_security_group_rule) |
| `module.dependencies.aws_security_group.mq` | `module.dependencies` | RECONFIGURE / MEDIUM | not written by this draft (stackit_security_group, stackit_security_group_rule) |
| `module.dependencies.module.catalog_rds.aws_security_group.this` | `module.dependencies.module.catalog_rds` | RECONFIGURE / MEDIUM | not written by this draft (stackit_security_group, stackit_security_group_rule) |
| `module.dependencies.module.checkout_elasticache_redis.module.aws_security_group.aws_security_group.cbd` | `module.dependencies.module.checkout_elasticache_redis.module.aws_security_group` | RECONFIGURE / MEDIUM | not written by this draft (stackit_security_group, stackit_security_group_rule) |
| `module.dependencies.module.orders_rds.aws_security_group.this` | `module.dependencies.module.orders_rds` | RECONFIGURE / MEDIUM | not written by this draft (stackit_security_group, stackit_security_group_rule) |
| `module.retail_app_ecs.module.alb.aws_lb.this` | `module.retail_app_ecs.module.alb` | RECONFIGURE / MEDIUM | STACKIT Application Load Balancer |
| `module.retail_app_ecs.module.carts_service.aws_ecs_service.this` | `module.retail_app_ecs.module.carts_service` | REPLATFORM / LOW | STACKIT Kubernetes Engine (SKE) |

## Wave 4 — 5 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.dependencies.aws_mq_broker.mq` | `module.dependencies` | RECONFIGURE / MEDIUM | STACKIT RabbitMQ |
| `module.dependencies.module.catalog_opensearch.aws_opensearch_domain.this` | `module.dependencies.module.catalog_opensearch` | REPLATFORM / LOW | STACKIT OpenSearch |
| `module.dependencies.module.catalog_rds.aws_rds_cluster.this` | `module.dependencies.module.catalog_rds` | REPLATFORM / LOW | STACKIT MariaDB |
| `module.dependencies.module.checkout_elasticache_redis.aws_elasticache_replication_group.default` | `module.dependencies.module.checkout_elasticache_redis` | RECONFIGURE / MEDIUM | STACKIT Key Value Store (Valkey) |
| `module.dependencies.module.orders_rds.aws_rds_cluster.this` | `module.dependencies.module.orders_rds` | REPLATFORM / MEDIUM | STACKIT PostgreSQL Flex |

## Wave 5 — 3 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.aws_secretsmanager_secret.catalog_db` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |
| `module.retail_app_ecs.aws_secretsmanager_secret.mq` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |
| `module.retail_app_ecs.aws_secretsmanager_secret.orders_db` | `module.retail_app_ecs` | RECONFIGURE / MEDIUM | STACKIT Secrets Manager |

## Wave 6 — 2 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.module.catalog_service.aws_iam_role.task_execution_role` | `module.retail_app_ecs.module.catalog_service` | RECONFIGURE / LOW | STACKIT service account for the workload |
| `module.retail_app_ecs.module.orders_service.aws_iam_role.task_execution_role` | `module.retail_app_ecs.module.orders_service` | RECONFIGURE / LOW | STACKIT service account for the workload |

## Wave 7 — 2 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.module.catalog_service.aws_ecs_service.this` | `module.retail_app_ecs.module.catalog_service` | REPLATFORM / LOW | STACKIT Kubernetes Engine (SKE) |
| `module.retail_app_ecs.module.orders_service.aws_ecs_service.this` | `module.retail_app_ecs.module.orders_service` | REPLATFORM / LOW | STACKIT Kubernetes Engine (SKE) |

## Wave 8 — 1 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.module.checkout_service.aws_ecs_service.this` | `module.retail_app_ecs.module.checkout_service` | REPLATFORM / MEDIUM | STACKIT Kubernetes Engine (SKE) |

## Wave 9 — 1 unit(s)

| Unit | Module | Class | Target |
|---|---|---|---|
| `module.retail_app_ecs.module.ui_service.aws_ecs_service.this` | `module.retail_app_ecs.module.ui_service` | REPLATFORM / MEDIUM | STACKIT Kubernetes Engine (SKE) |

## Configuration decided at plan time

5 unit(s) below exist, but part of what configures them (a facet) is decided only when OpenTofu plans, or may not belong to them. They stay in their waves and in the totals; they are not automation-eligible until that part is known.

| Unit | Wave | Open |
|---|---:|---|
| `module.retail_app_ecs.module.carts_service.aws_iam_role.task_role` | 2 | `module.retail_app_ecs.module.carts_service.aws_iam_role_policy_attachment.cloudwatch_agent` is switched off by default (the default of variable `var.opentelemetry_enabled`; a root variable that a variable file or the command line can override): nothing of it is drafted, and a variable file or `-var` that gives that input another value creates it |
| `module.retail_app_ecs.module.catalog_service.aws_iam_role.task_role` | 2 | `module.retail_app_ecs.module.catalog_service.aws_iam_role_policy_attachment.cloudwatch_agent` is switched off by default (the default of variable `var.opentelemetry_enabled`; a root variable that a variable file or the command line can override): nothing of it is drafted, and a variable file or `-var` that gives that input another value creates it |
| `module.retail_app_ecs.module.checkout_service.aws_iam_role.task_role` | 2 | `module.retail_app_ecs.module.checkout_service.aws_iam_role_policy_attachment.cloudwatch_agent` is switched off by default (the default of variable `var.opentelemetry_enabled`; a root variable that a variable file or the command line can override): nothing of it is drafted, and a variable file or `-var` that gives that input another value creates it |
| `module.retail_app_ecs.module.orders_service.aws_iam_role.task_role` | 2 | `module.retail_app_ecs.module.orders_service.aws_iam_role_policy_attachment.cloudwatch_agent` is switched off by default (the default of variable `var.opentelemetry_enabled`; a root variable that a variable file or the command line can override): nothing of it is drafted, and a variable file or `-var` that gives that input another value creates it |
| `module.retail_app_ecs.module.ui_service.aws_iam_role.task_role` | 2 | `module.retail_app_ecs.module.ui_service.aws_iam_role_policy_attachment.cloudwatch_agent` is switched off by default (the default of variable `var.opentelemetry_enabled`; a root variable that a variable file or the command line can override): nothing of it is drafted, and a variable file or `-var` that gives that input another value creates it |

## Cutover (decision support — performed by the customer)

No cutover facts: the scan and the draft established no DNS record set whose value the draft re-binds to a generated address, no public address re-binding, no DNS record unit, no certificate unit and no open cutover decision. That is not a statement that nothing has to be cut over: a name, an address or a certificate outside the scanned source is not seen, and a unit that exists only if OpenTofu decides so at plan time is not read here. StackToIT performs no cutover and gives no time estimate.

## Not in a wave — switched off by configuration

41 unit(s) produce no instance with the current values (their count/for_each is known to be zero), so they are in no wave and nothing depends on them. They move into the plan only if the configuration is changed to create them. The units inside a module call are counted per outermost call; `engineering/architect-report.md` lists every one with its cause.

- `module.dependencies` — 13 unit(s) (count = 0 ×10 · for_each = 0 ×3): `module.dependencies.module.catalog_opensearch.aws_cloudwatch_log_group.this`, `module.dependencies.module.catalog_opensearch.aws_cloudwatch_log_resource_policy.this`, `module.dependencies.module.catalog_opensearch.aws_security_group.this`, `module.dependencies.module.catalog_rds.aws_cloudwatch_log_group.this` and 9 more
- `module.retail_app_ecs` — 3 unit(s) (count = 0 ×2 · for_each = 0 ×1): `module.retail_app_ecs.module.alb.aws_lambda_permission.lb`, `module.retail_app_ecs.module.alb.aws_wafv2_web_acl_association.this`, `module.retail_app_ecs.module.alb_sg.aws_security_group.this`
- `module.vpc` — 25 unit(s) (count = 0 ×24 · for_each = 0 ×1): `module.vpc.module.vpc.aws_cloudwatch_log_group.flow_log`, `module.vpc.module.vpc.aws_default_vpc.this`, `module.vpc.module.vpc.aws_flow_log.this`, `module.vpc.module.vpc.aws_iam_role.vpc_flow_log_cloudwatch` and 21 more

## Before wave 1

- [ ] Every prerequisite above is resolved (module vendored or `tofu init` run, count/for_each inputs known) and the assessment is run again.
- [ ] The target project is created outside a Network Area: `module.vpc.module.vpc.aws_route_table.private`, `module.vpc.module.vpc.aws_route_table.public` are replaced by STACKIT's default routing, which was observed (tested on a STACKIT project on 2026-10-10) only in a project outside a Network Area (the default routing table of an area was never read: 403). A project inside an existing Network Area is not covered; the architect decides these tables there.
- [ ] Architect has reviewed every MANUAL_REVIEW, REDESIGN and BLOCKED unit in engineering/architect-report.md.
- [ ] STACKIT organisation, folders and projects are laid out (one project per environment is the usual start).
- [ ] Data-transfer method and cutover window agreed per data unit (databases, buckets, caches).
