MIGRATION STRATEGY · ANY SOURCE → STACKIT
Rehost, replatform, refactor or redesign: choosing per workload for STACKIT
Choose the strategy per unit, not per estate. In a small AWS estate assessed by StackToIT on 4 November 2026, one of 12 units needed only a data copy, seven needed configuration work, two moved to a different platform model, one became a container and one needed its data layer redesigned. The class StackToIT writes on each unit tells you which kind of work you are actually signing up for, before a single server moves.
The four strategies against the classes StackToIT writes
Rehost, replatform and refactor come from the vendors' migration frameworks; AWS files refactor together with re-architect, and redesign is used here for that re-architecting case. StackToIT does not label units with these names: it writes a class per unit, and the classes below are the closest reading.
| Strategy | Closest StackToIT class | What it means in the plan |
|---|---|---|
| Rehost (lift and shift) | DIRECT, RECONFIGURE | The service has a STACKIT counterpart with the same interface or the same shape. Settings, images, sizes and credentials change; the application does not. |
| Replatform | REPLATFORM | The workload moves to a different platform model, such as a managed database or a message broker. Clients switch driver, protocol or connection details. |
| Refactor | CONTAINERIZE | The code keeps its logic but loses its execution model. The handler is wrapped in an always-on process and the triggers are rebuilt. |
| Redesign | REDESIGN | There is no compatible service. The data model and the access layer are rewritten against a different kind of store. |
AWS Prescriptive Guidance defines rehost as a move without changes to the application, replatform as a move with some optimisation, and refactor as the most complex and costly strategy; for large migrations it recommends modernising after the move. AWS counts moving virtual machines into containers as replatform; the CONTAINERIZE unit here sits closer to refactor because a function also loses its event-driven execution model. The mapping of those names onto classes is ours, not a StackToIT output.
Rehost: a virtual machine becomes a server
From a run of a 13-resource AWS estate written for this page. Left: the instance as the source declares it. Right: the server block StackToIT drafted; the review comments above it in the file are left out here.
resource "aws_instance" "legacy_erp" {
ami = "ami-0abcdef1234567890"
instance_type = "m6i.xlarge"
subnet_id = aws_subnet.app.id
vpc_security_group_ids = [aws_security_group.web.id]
}resource "stackit_server" "legacy_erp" {
project_id = var.project_id
name = "legacy-erp"
machine_type = var.legacy_erp_machine_type
availability_zone = var.availability_zone
boot_volume = {
source_type = "image"
source_id = var.legacy_erp_image_id
delete_on_termination = true
size = var.legacy_erp_boot_volume_size_gb
}
network_interfaces = [stackit_network_interface.legacy_erp.network_interface_id]
keypair_name = var.operator_keypair_name
}Class: RECONFIGURE
The instance maps to a STACKIT server. The unit keeps its shape and the architect fills in what the source cannot state.
Size and image are variables
The machine type and the image are variables. The type variable states the source size, m6i.xlarge at about 4 vCPU and 16 GiB, and links the STACKIT machine types; the AMI has to become a public image or an imported raw or qcow2 image.
Nothing in the application changes
This is the cheapest kind of unit in the plan. It still waits for a boot image decision before the server can be created.
Redesign: a key-value table has no counterpart
From the same run. Left: the DynamoDB table. Right: the MongoDB Flex instance the draft offers as an alternative; comments above the block are left out.
resource "aws_dynamodb_table" "sessions" {
name = "sessions"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
}resource "stackit_mongodbflex_instance" "dynamodb_tables" {
project_id = var.project_id
name = "dynamodb-tables"
acl = var.dynamodb_tables_allowed_cidrs
version = var.dynamodb_tables_version
flavor = {
cpu = var.dynamodb_tables_cpu
ram = var.dynamodb_tables_ram
}
replicas = 3
storage = {
class = var.mongodbflex_storage_class
size = var.dynamodb_tables_storage_gb
}
backup_schedule = "0 2 * * *"
options = {
type = "Replica"
point_in_time_window_hours = var.dynamodb_tables_pitr_hours
}
}Class: REDESIGN
The run states that no DynamoDB-compatible service exists on STACKIT. The draft is an alternative, not an equivalent: one document store instance for the estate's tables, with PostgreSQL Flex and JSONB named as the other option.
Capacity does not translate
CPU and memory are variables to size from the observed load, because DynamoDB capacity units have no counterpart. Key design, conditional writes and capacity modes do not carry over.
The work is in the code
The review items ask for the data access layer to be rewritten against the new API. That is application work, scheduled with the application team.
Containerize: a function becomes an always-on app
From the same run. Left: the Lambda function. Right: the Cloud Foundry manifest the draft wrote for it, as the file holds it after its comment header.
resource "aws_lambda_function" "order_worker" {
function_name = "order-worker"
role = aws_iam_role.worker.arn
runtime = "python3.12"
handler = "app.handler"
filename = "worker.zip"
}---
applications:
- name: "order-worker"
memory: 128M # the Lambda default memory_size
instances: 1 # one always-on instance; size from peak concurrency (App AutoScaler for elasticity)
stack: cflinuxfs4
buildpacks:
- python_buildpack_offline
no-route: true
health-check-type: process
Class: CONTAINERIZE
A function does not move as a function. Its handler runs inside a process that stays up, so billing per invocation and scale to zero are gone.
What the manifest does not carry
The file names what it leaves out: the handler entry point, the per-invocation timeout, the execution role and the deployment package. A person adds an HTTP server or worker loop and decides how the function gets its credentials.
Triggers are rebuilt
The draft carries no trigger. Whatever invoked the function must feed or call the new app another way.
The twelve units of the run, by class
| Source unit | STACKIT target | Class |
|---|---|---|
| aws_s3_bucket.invoices | Object Storage | DIRECT: data copy and new access keys |
| aws_instance.legacy_erp | Compute Engine | RECONFIGURE: machine type and image |
| aws_iam_role.worker | Service account for the workload | RECONFIGURE: permissions become role assignments |
| aws_vpc.main, three subnets, security group | Project networking, networks, security group | RECONFIGURE: seven units in all with the instance, role and these |
| aws_db_instance.orders | PostgreSQL Flex | REPLATFORM: dump and restore or logical replication |
| aws_sqs_queue.jobs | RabbitMQ | REPLATFORM: producers and consumers move to AMQP |
| aws_lambda_function.order_worker | Cloud Foundry app (alternative) | CONTAINERIZE: an always-on process |
| aws_dynamodb_table.sessions | MongoDB Flex (alternative) | REDESIGN: new data model and access layer |
13 resources became 12 units; the database subnet group is folded into the database. By class: 1 DIRECT, 7 RECONFIGURE, 2 REPLATFORM, 1 CONTAINERIZE, 1 REDESIGN, all with MEDIUM confidence. 11 units got a draft and 1 needs no STACKIT resource of its own.
How to choose, step by step
Assess first, choose second
Run the assessment on the whole estate and read the class of every unit before assigning a strategy to any application. The class is evidence from the source configuration, not a preference.
Default to the cheapest class that holds
Let DIRECT and RECONFIGURE units move as they are. The Microsoft Cloud Adoption Framework advises starting with simpler, lower-risk workloads to build confidence and refine the process.
Separate the REDESIGN units
Treat each REDESIGN unit as a small software project with its own owner and date. Do not let it hold the infrastructure waves back; an unfinished data layer is what keeps that unit from cutting over.
Replatform where the data moves
REPLATFORM units carry data movement. The run writes a data move runbook per database and leaves the method open, because the size of the data and the tolerated downtime are not in the source.
Answer, rerun, compare
Put configuration answers in an inputs file and architect reviews in a decisions file, both copied from the templates the run writes, and run again. Inputs can change the draft; a recorded review alone does not, so read the new draft and execution plan after every rerun.
Decisions the architect owns
Which replacement for a missing service
MongoDB Flex or PostgreSQL Flex with JSONB for the table. The run offers one and names the other; the choice follows the access patterns of the application.
Function runtime
A Cloud Foundry app, or a container on SKE or Container Applications. The draft writes only the Cloud Foundry option; for a container, building the image is your work.
Database move method
A dump restored inside a write freeze or logical replication. The run defines both and chooses neither.
When to modernise
Whether a RECONFIGURE or REPLATFORM unit is modernised during the move or afterwards. For large moves AWS Prescriptive Guidance recommends afterwards.
Questions architects ask
Does StackToIT assign rehost, replatform, refactor or redesign to each application?
No. It assigns a class to each unit of the source configuration: DIRECT, RECONFIGURE, REPLATFORM, CONTAINERIZE, REDESIGN, MANUAL_REVIEW or BLOCKED. An application strategy is a decision you take from those classes, and the application mapping file lets you group units into applications.
Is a pure rehost possible on STACKIT?
For virtual machines and for S3-compatible object storage, largely yes: the run classes them DIRECT or RECONFIGURE, and the application does not change. Even then the image, the machine type, the credentials and the network addressing are decisions, so the unit is configured, not copied.
Why is a function not a replatform?
The run states that STACKIT has no function-as-a-service that is generally available, so the handler has to be wrapped in a process that stays up and the triggers rebuilt. That is a change of execution model, which is why the class is CONTAINERIZE and not REPLATFORM.
Should the REDESIGN units go first or last?
Start the design work early and the infrastructure waves in parallel. The data layer is the long pole for those units, so the application team needs the time even though the cutover of that unit comes with its wave.
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.