Asia/Calcutta
Posts

AWS Migration: t3.micro/small → m7i-flex.large for ML Workloads

March 21, 2026
The t3.small and t3.micro are great entry-level instances, but once you add ML inference, background task queues (Celery), or data-heavy APIs, you hit their ceiling fast — 2GB RAM, burstable CPU that throttles under load, and no memory bandwidth headroom for NumPy or scikit-learn. This guide covers which instance to move to, why, and how to migrate without losing AWS credits or causing downtime.
Limitationt3.microt3.smallImpact
RAM1 GB2 GBModel loading OOM
CPU modelBurstable (10–20% baseline)Burstable (20% baseline)Training throttles hard
Memory typeDDR4 (older gen)DDR4Slow data pipelines
ML instructionsSSE/AVX onlySSE/AVX onlyNo matrix acceleration
Burst credit depletionFastFastSustained tasks crawl

InstancevCPURAMHourlyMonthlyBest For
t3.small22 GB$0.023~$17Dev/test only
t3.medium24 GB$0.047~$34Light API
m5.large28 GB$0.096~$70Stable baseline
m6i.large28 GB$0.096~$70API-heavy workloads
m7i-flex.large28 GB$0.0958~$70ML + Celery + API
m5.xlarge416 GB$0.192~$140Heavy ML training
Recommendation: m7i-flex.large — same price as m6i but with a newer processor, DDR5 memory, and hardware ML acceleration (AMX).
Aspectm6i.largem7i-flex.large
Processor3rd Gen Intel Xeon (Ice Lake)4th Gen Intel Xeon (Sapphire Rapids)
Base Frequency2.6 GHz2.6 GHz
Turbo FrequencyUp to 3.5 GHzUp to 3.8 GHz
Instruction SetsSSE, AVX, AVX2SSE, AVX, AVX2, AMX
CPU Baseline100% always40% baseline → bursts to 100%
Aspectm6i.largem7i-flex.large
Memory TypeDDR4DDR5
RAM8 GB8 GB
Memory Bandwidth~80 GB/s~160 GB/s
Network Bandwidth10 Gbps12.5 Gbps
EBS Bandwidth10 Gbps10 Gbps
AMX (Advanced Matrix Extensions) on Sapphire Rapids provides up to 10x faster matrix/dot-product operations — directly benefits NumPy, scikit-learn, TensorFlow CPU, and XGBoost.
  • m6i.large — consistent baseline (100% CPU always available), no throttling, predictable latency
  • m7i-flex.large — 5% faster at peak, but 40% baseline can cause queue buildup under steady API traffic
  • Winner for API-heavy: m6i.large
  • m7i-flex.large wins due to AMX acceleration and 2x memory bandwidth (DDR5)
  • Estimated training speedup on RandomForest (1 GB dataset): ~15% faster at full burst
  • At 40% baseline: ~2x slower — schedule ML jobs to avoid baseline throttling
  • Winner for ML: m7i-flex.large
  • Short, bursty jobs fit perfectly with m7i-flex burst model
  • Long-running continuous tasks risk hitting the 40% baseline ceiling
  • Winner for bursty Celery: m7i-flex.large
ScenarioRecommendationReason
API dominant (>80%)m6i.largeNo throttling risk
ML dominant (>80%)m7i-flex.largeAMX + DDR5
Celery dominant (>80%)m7i-flex.largeBurst fits bursty jobs
Balanced mixm7i-flex.largeSlightly cheaper, newer gen
Reliability-criticalm6i.largePredictable baseline

Pricing Modelm6i.largem7i-flex.large
On-Demand$70/mo$70/mo
1-Year Savings Plan~$56/mo~$56/mo
3-Year Savings Plan~$49/mo~$49/mo
Spot (~70% off)~$21/mo~$21/mo
For 24/7 production: use a 1-Year Savings Plan ($56/mo). For batch ML jobs: Spot instances ($21/mo) work well since interruptions are acceptable.
Your AWS credits will not be lost. Credits apply at the account level, not per instance. Both old and new instances consume credits from the same pool.
1. Document your current config:
# Note down these before touching anything
# - Security group IDs
# - IAM role name
# - EBS volume IDs and sizes
# - Elastic IP allocation ID (if any)
# - Environment variables / .env files
2. Backup application data to S3:
tar -czf ~/backup.tar.gz /app
aws s3 cp ~/backup.tar.gz s3://your-bucket/backups/migration-$(date +%Y%m%d).tar.gz
3. Get your instance ID:
aws ec2 describe-instances \
  --filters "Name=instance-type,Values=t3.micro" \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --region us-east-1
# Output: i-0123456789abcdef0
4. Stop the t3.micro (don't terminate):
aws ec2 stop-instances --instance-ids i-0123456789abcdef0 --region us-east-1
aws ec2 wait instance-stopped --instance-ids i-0123456789abcdef0 --region us-east-1
5. Create an AMI from the stopped instance:
aws ec2 create-image \
  --instance-id i-0123456789abcdef0 \
  --name "t3-micro-backup-$(date +%Y%m%d)" \
  --description "Backup before m7i-flex migration" \
  --region us-east-1
# Output: { "ImageId": "ami-0abc123def456ghi" }
Save the ImageId — you'll launch from it. 6. Launch new instance from the AMI:
aws ec2 run-instances \
  --image-id ami-0abc123def456ghi \
  --instance-type m7i-flex.large \
  --key-name your-keypair-name \
  --security-group-ids sg-0123456789abcdef0 \
  --iam-instance-profile Name=your-iam-role \
  --region us-east-1 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=app-m7i-flex}]'
7. Get the new public IP:
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=app-m7i-flex" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --region us-east-1
8. SSH in and check everything:
ssh -i your-key.pem ec2-user@<new-public-ip>

# Confirm instance type
curl http://169.254.169.254/latest/meta-data/instance-type
# Should return: m7i-flex.large

# Check RAM
free -h
# Should show ~8GB

# Check services
docker ps                        # if using Docker
systemctl status your-app        # if using systemd
celery -A app inspect active     # if using Celery

# Test API
curl http://localhost:8000/health
9. Reassign Elastic IP (if you have one):
# Disassociate from old instance
aws ec2 disassociate-address --association-id eipassoc-abc123 --region us-east-1

# Associate with new instance
aws ec2 associate-address \
  --instance-id i-new123456 \
  --allocation-id eipalloc-abc123 \
  --region us-east-1
10. Once stable, terminate the old instance:
# ⚠️ Only run this after 24+ hours of verified stable operation
aws ec2 terminate-instances \
  --instance-ids i-0123456789abcdef0 \
  --region us-east-1
11. Clean up old snapshots (optional):
# List your snapshots
aws ec2 describe-snapshots \
  --owner-ids self \
  --region us-east-1 \
  --query 'Snapshots[*].[SnapshotId,StartTime,Description]' \
  --output table

# Delete old ones you no longer need
aws ec2 delete-snapshot --snapshot-id snap-old123456 --region us-east-1

Save as migrate.sh and fill in your values:
#!/bin/bash
set -e

INSTANCE_ID="i-0123456789abcdef0"   # Your t3.micro ID
REGION="us-east-1"
SECURITY_GROUP="sg-0123456789abcdef0"
IAM_ROLE="your-iam-role"
KEYPAIR="your-keypair-name"

echo "▶ Stopping old instance..."
aws ec2 stop-instances --instance-ids $INSTANCE_ID --region $REGION
aws ec2 wait instance-stopped --instance-ids $INSTANCE_ID --region $REGION
echo "✓ Instance stopped"

echo "▶ Creating AMI..."
AMI_ID=$(aws ec2 create-image \
  --instance-id $INSTANCE_ID \
  --name "migration-$(date +%Y%m%d-%H%M%S)" \
  --region $REGION \
  --query 'ImageId' \
  --output text)
echo "✓ AMI created: $AMI_ID"

echo "▶ Waiting for AMI to be available..."
aws ec2 wait image-available --image-ids $AMI_ID --region $REGION

echo "▶ Launching m7i-flex.large..."
NEW_INSTANCE=$(aws ec2 run-instances \
  --image-id $AMI_ID \
  --instance-type m7i-flex.large \
  --key-name $KEYPAIR \
  --security-group-ids $SECURITY_GROUP \
  --iam-instance-profile Name=$IAM_ROLE \
  --region $REGION \
  --query 'Instances[0].InstanceId' \
  --output text)
echo "✓ New instance: $NEW_INSTANCE"

aws ec2 wait instance-running --instance-ids $NEW_INSTANCE --region $REGION

NEW_IP=$(aws ec2 describe-instances \
  --instance-ids $NEW_INSTANCE \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --region $REGION \
  --output text)

echo ""
echo "✅ Migration complete!"
echo "   New instance: $NEW_INSTANCE"
echo "   Public IP:    $NEW_IP"
echo "   SSH:          ssh -i $KEYPAIR.pem ec2-user@$NEW_IP"
echo ""
echo "⚠️  Test for 24h, then terminate old instance:"
echo "   aws ec2 terminate-instances --instance-ids $INSTANCE_ID --region $REGION"
chmod +x migrate.sh
./migrate.sh

Phaset3.microm7i-flexRunning Cost
BeforeRunning~$5/mo
During migration (~2h)StoppedStarting+$0.19
Testing window (24h)StoppedRunning+$2.30
After cleanupTerminatedRunning~$70/mo
Total extra cost during migration: ~$2.50 — negligible.
  • Instance type confirmed as m7i-flex.large
  • RAM shows ~8 GB (free -h)
  • All services running (Docker / systemd / Celery)
  • API endpoints respond correctly
  • Celery tasks execute and complete
  • Database connections established
  • File uploads / downloads work
  • Elastic IP / DNS routing updated
  • No errors in logs for 24+ hours
  • Old instance terminated

Track instance changes and migration history:
# In your infrastructure config folder
git init
git add .
git commit -m "Initial: t3.micro production config"

# After migration
git commit -m "Migrated t3.micro → m7i-flex.large for ML workloads"
This gives you a rollback reference and a changelog for every infrastructure decision.