Cloud Modernization Frameworks: Migrating Legacy Workloads to AWS and GKE

A cloud modernization framework is a repeatable decision process for moving legacy workloads to the cloud. It tells you, for each application, whether to rehost, replatform, refactor, or retire it, and it defines the sequence, guardrails, and success criteria for doing so on platforms like AWS and Google Kubernetes Engine (GKE). Without one, migrations tend to become a series of one-off projects with inconsistent security, unpredictable cost, and no clear finish line. With one, you can classify a portfolio of hundreds of applications, move them in controlled waves, and know which ones deserve deep re-engineering and which should simply be lifted and shifted.
This post walks through a practical framework we recommend for teams migrating to AWS, GKE, or both. It covers how to assess workloads, choose a disposition, build a landing zone, and avoid the failure modes that stall most modernization programs.
Why Legacy Migrations Stall Without a Cloud Modernization Framework
Most organizations don't fail at migration because the cloud is hard. They fail because they make the same decision hundreds of times without a consistent rubric. The usual symptoms:
- Analysis paralysis. Every application gets debated from scratch, so the backlog never shrinks.
- Over-refactoring. Teams rewrite stable, low-value systems into microservices and burn the budget before reaching the workloads that matter.
- Under-refactoring. Everything is rehosted onto VMs, and the operating model and cost profile end up looking just like the data center's, only with a monthly bill.
- Inconsistent foundations. Each team builds its own networking, IAM, and logging, which creates audit gaps that surface late.
A framework addresses all four by separating portfolio decisions (what happens to each app) from platform decisions (where and how it runs) and from execution (how it moves).
The Rs: Choosing a Disposition for Each Workload
The most widely used vocabulary for migration decisions traces back to Gartner's "5 Rs" model, which AWS later extended. AWS Prescriptive Guidance now describes seven strategies:
- Retire. Decommission applications nobody uses. This is often the cheapest win.
- Retain. Leave it where it is for now, usually because of licensing, latency, or a pending replacement.
- Rehost (lift and shift). Move VMs as-is, for example with AWS Application Migration Service or Google Cloud's Migrate to Virtual Machines.
- Relocate. Move at the hypervisor level, such as VMware workloads to VMware Cloud on AWS or Google Cloud VMware Engine.
- Repurchase. Replace with SaaS.
- Replatform (lift, tinker, and shift). Make targeted changes, such as moving a self-managed database to Amazon RDS or Cloud SQL, or containerizing an app without rewriting it.
- Refactor / re-architect. Redesign the application to use cloud-native capabilities.
The key point is that disposition is a per-workload decision, not a program-wide one. A healthy portfolio usually contains all seven. The framework's job is to make that classification fast and defensible.
A Five-Phase Cloud Modernization Framework
The phases below map loosely to the AWS Cloud Adoption Framework (AWS CAF) and Google Cloud's migration guidance ("assess, plan, deploy, optimize"). We've combined them into a structure that works across both providers.
Phase 1: Discover and Assess
Start with data, not opinions. Use automated discovery (AWS Application Discovery Service, AWS Migration Hub, or Google Cloud Migration Center) to collect server inventory, utilization, and network dependencies. Then enrich that data with information only humans know: business criticality, owner, compliance scope, and change frequency.
We recommend capturing each workload in a structured, version-controlled record so that decisions are reviewable:
# workloads/claims-intake.yaml
name: claims-intake
owner: claims-platform-team
business_criticality: high # high | medium | low
compliance_scope: [pii, sox]
runtime: java-8-tomcat
os: rhel-7
data_stores:
- type: oracle-19c
size_gb: 850
dependencies:
inbound: [web-portal, partner-sftp]
outbound: [policy-core, document-store]
change_frequency: weekly
proposed_disposition: replatform
target_platform: gke
rationale: >
Stateless app tier, frequent releases, team already uses containers.
Database moves to managed Postgres in a later wave after schema review.
Keeping these records in Git gives you an audit trail and makes it easy to generate wave plans programmatically.
Phase 2: Decide the Target Platform
AWS and GKE are not mutually exclusive, and many enterprises run both. Choose based on fit rather than preference:
- Amazon EC2, ECS, or EKS on AWS fit well when workloads depend on the AWS service ecosystem, when you're rehosting VMs at scale, or when existing teams and contracts are AWS-centric.
- GKE fits well when the target is Kubernetes-first, when teams want a managed control plane with options like GKE Autopilot, or when workloads integrate with Google Cloud data services such as BigQuery.
- Either works for standard containerized web services. In those cases, organizational factors (skills, existing commitments, data gravity) should decide.
Write the decision criteria down. "We chose GKE because the app is stateless, releases weekly, and its downstream analytics run in BigQuery" survives an architecture review. "We like Kubernetes" doesn't.
Phase 3: Build the Landing Zone First
A landing zone is the pre-configured, governed environment that workloads migrate into: account or project structure, networking, identity, logging, and guardrails. On AWS, AWS Control Tower and AWS Organizations provide the scaffolding. On Google Cloud, the Google Cloud enterprise foundations blueprint and its Terraform modules serve a similar role.
Do not migrate the first production workload before this exists. Retrofitting centralized logging and least-privilege IAM across dozens of live systems is far more expensive than building them first.
Define the foundation as code from day one:
# Organization-level guardrail: restrict resource locations on Google Cloud
resource "google_org_policy_policy" "allowed_locations" {
name = "organizations/${var.org_id}/policies/gcp.resourceLocations"
parent = "organizations/${var.org_id}"
spec {
rules {
values {
allowed_values = ["in:us-locations"]
}
}
}
}
The AWS equivalent is a Service Control Policy that denies actions outside approved regions. Either way, guardrails belong at the organization level, not in each team's pipeline.
Phase 4: Migrate in Waves
Group workloads into waves based on dependencies, not org charts. Applications that talk to each other heavily should move together or be separated by a well-defined interface. Early waves should be low-risk and representative, so they validate tooling and runbooks without endangering critical systems.
For applications being refactored, the strangler fig pattern (described by Martin Fowler) is the safest approach. Put a routing layer in front of the legacy system, carve off functionality one route at a time into new services, and retire the old code paths as traffic shifts. On AWS this layer is often an Application Load Balancer or API Gateway. On GKE it is typically the Gateway API or an Ingress.
For databases, use change data capture to keep source and target in sync until cutover. AWS Database Migration Service and Google Cloud's Database Migration Service both support continuous replication, which reduces cutover to a short, rehearsed window instead of a weekend outage.
Phase 5: Operate and Optimize
Migration is not the finish line. Once a workload is stable, review rightsizing, autoscaling policies, and commitment-based discounts, and schedule the next modernization step if the workload was rehosted as an interim move. Track a small set of outcomes per workload: deployment frequency, change failure rate, recovery time, and unit cost. The DORA research program's metrics are a sensible, well-documented starting point.
Practical Pattern: Replatforming a Legacy Service onto GKE or EKS
Containerizing without rewriting is often the highest-leverage move for legacy Java or .NET services. Two things matter most: externalizing configuration and replacing static credentials with workload identity.
On GKE, Workload Identity Federation lets a Kubernetes service account act as a Google Cloud service account without key files:
apiVersion: v1
kind: ServiceAccount
metadata:
name: claims-intake
namespace: claims
annotations:
iam.gke.io/gcp-service-account: claims-intake@my-project.iam.gserviceaccount.com
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: claims-intake
namespace: claims
spec:
replicas: 3
selector:
matchLabels: { app: claims-intake }
template:
metadata:
labels: { app: claims-intake }
spec:
serviceAccountName: claims-intake
containers:
- name: app
image: us-docker.pkg.dev/my-project/apps/claims-intake:1.4.2
envFrom:
- configMapRef: { name: claims-intake-config }
readinessProbe:
httpGet: { path: /health/ready, port: 8080 }
resources:
requests: { cpu: "500m", memory: "1Gi" }
limits: { memory: "1Gi" }
On Amazon EKS, the equivalent is IAM Roles for Service Accounts (annotation eks.amazonaws.com/role-arn) or EKS Pod Identity. The principle is the same: no long-lived secrets baked into images or environment variables.
Common Failure Modes to Plan Around
- Skipping dependency mapping. Undocumented calls to a mainframe or file share are the most common cause of failed cutovers.
- Treating rehost as the end state. Rehosting is a valid tactic, but put the follow-up modernization on the roadmap or it never happens.
- Ignoring licensing. Bring-your-own-license terms for databases and operating systems can change the economics of a target platform.
- Under-investing in observability. If you can't compare latency and error rates before and after migration, you can't prove the migration worked.
- No rollback plan. Every wave needs a tested way back.
Putting the Framework to Work
A cloud modernization framework is only useful if it produces decisions. Start with a time-boxed assessment of your portfolio, classify each workload with the Rs, stand up a governed landing zone, and run one representative wave end to end before scaling. If you're evaluating how a partner can support that work, you can review our cloud and engineering capabilities, and see how modernization priorities differ for regulated and high-scale environments on our industries we serve page.
FAQ
What is a cloud modernization framework?
A cloud modernization framework is a structured method for assessing legacy applications, assigning each a migration strategy (such as rehost, replatform, or refactor), and executing migrations in governed, repeatable waves. It aligns technical decisions with business priorities so modernization doesn't become a series of disconnected projects.
Should we migrate to AWS or GKE?
It depends on the workload. AWS offers broad options for VM rehosting and deep integration with its own managed services. GKE is a strong fit for Kubernetes-first, containerized workloads and for teams using Google Cloud data services. Many enterprises run both and decide per workload using documented criteria.
Is lift and shift a bad idea?
No. Rehosting is often the right first step for stable applications or when a data center exit has a fixed deadline. The risk is treating it as the final state. Plan a follow-up replatform or refactor step where the business case supports it.
How do we migrate databases with minimal downtime?
Use change data capture tools such as AWS Database Migration Service or Google Cloud Database Migration Service to replicate continuously from source to target. Validate data parity, rehearse the cutover, and switch application connections during a short, planned window with a tested rollback path.
Where should a modernization program start?
Start with automated discovery and a portfolio assessment, then build the landing zone before moving any production workload. Choose a low-risk but representative application for the first wave so you can validate tooling, runbooks, and guardrails before scaling.


