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.

StrategyClosest StackToIT classWhat it means in the plan
Rehost (lift and shift)DIRECT, RECONFIGUREThe service has a STACKIT counterpart with the same interface or the same shape. Settings, images, sizes and credentials change; the application does not.
ReplatformREPLATFORMThe workload moves to a different platform model, such as a managed database or a message broker. Clients switch driver, protocol or connection details.
RefactorCONTAINERIZEThe code keeps its logic but loses its execution model. The handler is wrapped in an always-on process and the triggers are rebuilt.
RedesignREDESIGNThere 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.

Example inputmain.tf
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]
}
STACKIT Terraform by StackToITterraform/compute.tf
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.

Example inputmain.tf
resource "aws_dynamodb_table" "sessions" {
  name         = "sessions"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "id"

  attribute {
    name = "id"
    type = "S"
  }
}
STACKIT Terraform by StackToITterraform/data.tf
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.

Example inputmain.tf
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"
}
STACKIT draft by StackToITterraform/cloudfoundry/order-worker/manifest.yml
---
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 unitSTACKIT targetClass
aws_s3_bucket.invoicesObject StorageDIRECT: data copy and new access keys
aws_instance.legacy_erpCompute EngineRECONFIGURE: machine type and image
aws_iam_role.workerService account for the workloadRECONFIGURE: permissions become role assignments
aws_vpc.main, three subnets, security groupProject networking, networks, security groupRECONFIGURE: seven units in all with the instance, role and these
aws_db_instance.ordersPostgreSQL FlexREPLATFORM: dump and restore or logical replication
aws_sqs_queue.jobsRabbitMQREPLATFORM: producers and consumers move to AMQP
aws_lambda_function.order_workerCloud Foundry app (alternative)CONTAINERIZE: an always-on process
aws_dynamodb_table.sessionsMongoDB 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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.