Plan and execute cloud migrations using proven patterns. Covers the 7 Rs of migration, lift-and-shift vs re-architecture, database migration strategies, cutover planning, and post-migration optimization.
Cloud migration patterns are the structured approaches engineers use to move workloads from on-premises infrastructure or legacy cloud environments into modern, scalable, resilient cloud platforms. These patterns define how applications, data, and services are transformed, decomposed, and reassembled across cloud boundaries—critical during organizational transformation, modernization initiatives, or when adopting cloud-native principles. Each pattern addresses a distinct challenge in the journey from monolith to distributed systems, and choosing the right one depends on existing assets, team maturity, and desired outcomes.
Move existing applications with minimal modification, preserving architecture and dependencies. Ideal for legacy systems with high development cost to refactor.
aws ec2 import-image to upload a disk image (VMDK, VHD) to Amazon EC2.ami-launch-configuration to set instance type, security groups, and user data.aws ec2 run-instances --image-id ami-12345678 --instance-type t3.large --key-name prod-key --security-groups web-sg.Key failure modes:
/health vs /status).Common confusions:
--block-device-mapping incorrectly: attaching EBS volumes but forgetting to mount them in the instance’s fstab.Apply cloud-specific enhancements with minimal code changes—improving performance and cost without full refactoring.
Example configuration:
Resources:
WebAppInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-12345678
InstanceType: t3.medium
SecurityGroups:
- Ref: WebSecurityGroup
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeSize: 50
VolumeType: gp2
DeleteOnTermination: true
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
yum install -y nginx
aws s3 cp s3://app-assets/config.json /etc/app/
systemctl enable nginx
systemctl start nginx
Sharp edges:
db.t3.medium underperforms on heavy OLTP workloads.Break monoliths into smaller, loosely coupled services, often with containerization and microservices principles.
docker build -t user-service:1.2.0 . and docker push registry.example.com/user-service:1.2.0.kubectl apply -f deployment.yaml, kubectl rollout restart deployment/user-service.Example deployment:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 4
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: registry.example.com/user-service:1.2.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: connection-string
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Failure modes:
user-service cannot resolve order-service via DNS or service mesh.user-service runs 1.2.0 but order-service expects 1.2.0 with a different schema./ready and /live endpoints not defined, causing rolling updates to fail silently.Build entirely new applications tailored to the cloud, using modern frameworks and cloud-native patterns.
aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/orders --message-body '{"orderId": "12345"}'.aws lambda create-function --function-name process-order --runtime python3.9 --handler index.handler --role arn:aws:iam::123456789012:role/lambda-exec.Example Terraform module:
# modules/order-processing/main.tf
resource "aws_lambda_function" "process_order" {
filename = "lambda.zip"
function_name = "process-order"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "python3.9"
timeout = 30
memory_size = 512
publish = true
environment {
variables = {
TABLE_NAME = aws_dynamodb_table.orders.name
}
}
tags = {
Environment = var.environment
Project = "OrderService"
}
}
resource "aws_event_source_mapping" "sqs_to_lambda" {
event_source_arn = aws_sqs_queue.orders.arn
function_name = aws_lambda_function.process_order.arn
batch_size = 10
maximum_batching_window_in_seconds = 300
}
Common pitfalls:
Remove outdated systems and consolidate workloads after migration.
aws s3 cp --recursive /data/ s3://archive-prod/ --storage-class STANDARD_IA.aws ec2 describe-instances --filter Name=tag:Retire,Values=true | jq -r '.Reservations[].Instances[].InstanceId' | xargs aws ec2 terminate-instances.Configuration example:
# script: retire-old-app.sh
#!/bin/bash
set -euo pipefail
export AWS_PROFILE=prod
# 1. Mark instances for retirement
aws ec2 create-tags \
--resources $(aws ec2 describe-instances \
--filters "Name=tag:Application,Values=LegacyApp" \
--query 'Reservations[].Instances[].InstanceId' \
--output text) \
--tags Key=Retire,Value=true
# 2. Start backup to S3
aws s3 sync /var/data/legacy-app s3://backup-legacy-app/ --delete
# 3. Terminate after 30 days
aws ec2 create-ami \
--instance-id i-1234567890abcdef0 \
--name "LegacyApp-Backup-$(date +%Y-%m-%d)" \
--description "Backup for retirement" \
--no-include-volume-attachments
# 4. Schedule termination
aws ec2 create-scheduled-action \
--scheduled-action-name "Retire-LegacyApp" \
--schedule "cron(0 0 1 * *)" \
--recurrence "monthly" \
--target-type "instance" \
--target-resource-id "i-1234567890abcdef0" \
--action-type "terminate" \
--start-time "2023-10-01T00:00:00Z" \
--end-time "2024-12-31T23:59:59Z"
Silent failures:
s3 sync skips unchanged files, but new files are missing.describe-instances query fails due to incorrect key names (Application vs App).Move data across environments with consistency, integrity, and minimal downtime.
rsync --archive --compress --partial --delete /data/ user@cloud:/data/.Example data migration:
# Sync data with incremental updates
rsync -avz --partial --delete \
--include='*/' \
--include='*.csv' \
--include='*.json' \
--exclude='*' \
/data/ \
user@cloud-host:/data/
# Monitor with log-based replication
# In MySQL:
SHOW SLAVE STATUS\G
-- Output includes:
-- Last_IO_Error: Got error 1045 from server: Access denied for user 'repl'@'%' (using password: YES)
-- Last_SQL_Error: Failed to execute transaction on table users
-- Seconds_Behind_Master: 32
# Verify data consistency
pg_dump -h old-db.example.com -U app_user -d legacy_app | \
pg_isready -h new-db.example.com -U app_user -d new_app
Failure modes:
Apply changes in small, predictable steps, minimizing risk and downtime.
Example:
# api-gateway.yaml
resources:
- type: AWS::ApiGateway::RestApi
properties:
name: user-api
description: "User service API"
endpointConfiguration:
types: ["REGIONAL"]
binaryMediaTypes:
- "application/json"
- "image/png"
# Route /users to both v1 and v2
- type: AWS::ApiGateway::Deployment
properties:
apiId: !Ref UserApi
stageName: v1
- type: AWS::ApiGateway::Stage
properties:
apiId: !Ref UserApi
stageName: v2
description: "Feature flag: new user creation"
variables:
feature.new-user.create: "true"
accessLogSettings:
destinationArn: arn:aws:logs:us-east-1:123456789012:log-group:/api/user-api
format: "$context.requestId $context.status $context.path $context.authorizer.claims.email"
Sharp edges:
{"name": "John"} but v2 expects {"firstName": "John"}.v1 stage not updated after v2 deployment.Maintain on-premises and cloud systems in parallel, with seamless integration.
kafka-console-producer.sh --broker-list kafka1:9092,kafka2:9092.aws dms start-replication-task --replication-task-arn arn:aws:dms:us-east-1:123456789012:task:xyz123.Common configuration:
// dms-task-configuration.json
{
"FullLoadSettings": {
"MaxFullLoadDistinctValueCount": 100000,
"TargetTablePrepMode": "TRUNCATE"
},
"TaskSettings": {
"Logging": {
"LogGroupName": "/aws/dms/replication-task",
"LogFileSize": 1024,
"LogRetentionInDays": 30
},
"ParallelLoad": {
"LoadParallelism": 4,
"LoadThreshold": 10000
}
}
}
Failure modes:
dms describe-replication-tasks shows Status: RUNNING but no data transferred.This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy