Módulo 6: Cloud Migration Patterns
1. Introducción: Cloud Migration Patterns
Descripción
Esta es la primera cápsula del Módulo 6 de la Guía de Deployment & Cloud Infrastructure. Este es el módulo más complejo de la guía — y probablemente el más valioso para tu carrera como ingeniero. Aquí vas a aprender los patrones de ingeniería que permiten que el mismo código funcione contra LocalStack en desarrollo y contra AWS en producción, sin cambiar una línea de lógica de negocio. Es lo que separa un prototipo que "funciona en mi máquina" de un sistema que opera en producción real.
Por qué importa: En los módulos anteriores aprendiste herramientas individuales: Docker Compose (M2), Lambda (M3), LocalStack (M4), AWS Services (M5). Cada una funciona en su contexto. Pero el problema real no es usar una herramienta — es migrar entre entornos sin romper nada. Tu código boto3 de LocalStack tiene endpoint_url="http://localhost:4566" hardcodeado. Tu config de AWS tiene credenciales diferentes. Tus tests asumen un entorno específico. Esto no escala. Este módulo enseña a diseñar tu aplicación para que la configuración decida el entorno y el código simplemente ejecute — idéntico en LocalStack, AWS staging, y AWS producción.
La promesa de LocalStack en el Módulo 4 fue: "desarrolla localmente, migra con confianza." Este módulo cumple esa promesa. Al terminar, tendrás una app AI que corre contra LocalStack y AWS con el mismo codebase, tests que verifican ambos entornos, y un migration runbook que otro ingeniero puede seguir paso a paso.
¿Dónde Estamos en la Guía?
Contexto
Phase 1: Deployment Strategies (Módulos 1-3)
├── Módulo 1: Understanding Deployment Options ✅ COMPLETADO
├── Módulo 2: Local & Container Deployment ✅ COMPLETADO
└── Módulo 3: Serverless & Lambda for AI ✅ COMPLETADO
Phase 2: Cloud Infrastructure & Migration (Módulos 4-6)
├── Módulo 4: LocalStack — AWS Local Development ✅ COMPLETADO
├── Módulo 5: AWS Services for AI ✅ COMPLETADO
└── Módulo 6: Cloud Migration Patterns ← ESTÁS AQUÍ
Phase 3: Alternatives & Production (Módulos 7-8)
├── Módulo 7: Alternative Platforms (Render, Railway, Fly.io)
└── Módulo 8: Proyecto Integrador — Deployed AI System
Duración total estimada de la guía: 10-12 horas (self-paced).
Transición desde Módulo 5
En el Módulo 5 profundizaste en AWS real: S3 como data layer, Lambda para inferencia, IAM con least privilege, integración event-driven, SageMaker basics, y cost estimation. Tienes un servicio AI funcional en AWS. Pero ese servicio tiene un problema: está acoplado a su entorno.
Si miras el código del M5, encontrarás:
- Endpoints hardcodeados —
endpoint_urlen algunos archivos, ausente en otros. Cada cambio de entorno requiere editar código. - Configuración dispersa — Variables de entorno aquí, constantes allá, credenciales mezcladas con lógica.
- Tests atados a un entorno — Tus tests funcionan contra LocalStack O contra AWS, pero no contra ambos con el mismo código.
- Sin degradación — Si S3 no responde, la app crashea. No hay fallback, no hay circuit breaker.
Este módulo resuelve cada uno de estos problemas con patrones de ingeniería concretos:
| Problema | Patrón | Cápsula |
|---|---|---|
| Endpoints hardcodeados | Environment Abstraction | 02 |
| Configuración dispersa | Config Management multi-entorno | 03 |
| Clients acoplados | Dependency Injection para boto3 | 04 |
| Tests atados a un entorno | Testing multi-entorno | 05 |
| Features no disponibles | Feature Flags cloud | 06 |
| Sin degradación | Graceful Degradation | 07 |
| Todo integrado | Proyecto: Migration-Ready AI App | 08 |
Qué Es Cloud Migration Patterns
El problema real: ambientes diferentes, mismo código
Desarrollo (LocalStack) Staging (AWS) Producción (AWS)
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ endpoint: localhost │ │ endpoint: AWS │ │ endpoint: AWS │
│ credentials: test │ │ credentials: IAM │ │ credentials: IAM │
│ S3: local bucket │ │ S3: staging bucket │ │ S3: prod bucket │
│ Lambda: local │ │ Lambda: staging │ │ Lambda: prod │
│ SageMaker: ❌ N/A │ │ SageMaker: ✅ │ │ SageMaker: ✅ │
│ IAM: no enforced │ │ IAM: enforced │ │ IAM: strict │
│ Costo: $0 │ │ Costo: bajo │ │ Costo: variable │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
│ │ │
└──────────────────────────┼─────────────────────────┘
│
MISMO CÓDIGO FUENTE
La meta es que tu aplicación no sepa (ni le importe) en qué entorno corre. La configuración le dice qué endpoints usar, qué credenciales, qué features están disponibles. El código ejecuta la misma lógica siempre.
Antes vs Después: el contraste que importa
Antes (código del M5, acoplado a un entorno):
import boto3
s3 = boto3.client("s3", endpoint_url="http://localhost:4566")
bucket = "ai-assets-dev"
def process_document(doc_key: str):
response = s3.get_object(Bucket=bucket, Key=doc_key)
content = response["Body"].read().decode("utf-8")
# ... procesamiento ...
return result
Problema: si quieres correr esto en AWS, necesitas editar el código. Eliminar endpoint_url, cambiar el bucket name. Si vuelves a desarrollo, editarlo de nuevo.
Después (código migration-ready):
from config import get_settings
from clients import get_s3_client
settings = get_settings()
s3 = get_s3_client(settings)
def process_document(doc_key: str):
response = s3.get_object(Bucket=settings.s3_bucket, Key=doc_key)
content = response["Body"].read().decode("utf-8")
# ... procesamiento identico ...
return result
Cambio de entorno: ENVIRONMENT=aws → la app conecta a AWS. ENVIRONMENT=local → conecta a LocalStack. Zero cambios en lógica de negocio.
Los 5 patrones de este módulo
Cloud Migration Patterns:
├── 1. Environment Abstraction
│ └── Abstraer endpoints y config para que el código sea agnóstico al entorno
│
├── 2. Config Management Multi-Entorno
│ └── Pydantic Settings + .env files + validación por entorno
│
├── 3. Dependency Injection para Clients
│ └── Factory pattern: inyectar boto3 clients configurados para el entorno correcto
│
├── 4. Testing Multi-Entorno
│ └── Mismo test suite contra LocalStack Y AWS con pytest fixtures
│
├── 5. Feature Flags + Graceful Degradation
│ └── Habilitar/deshabilitar features por entorno + degradar sin crashear
Estos no son patrones teóricos. Son código que implementarás y que tu app usará en producción real. Cada uno se construye sobre el anterior: primero abstraes (02), luego configuras (03), luego inyectas (04), luego pruebas (05), luego manejas lo que no está disponible (06-07).
Objetivo del Módulo
Al terminar este módulo serás capaz de:
- ✅ Implementar environment abstraction que permita al mismo código interactuar con LocalStack o AWS cambiando solo configuración
- ✅ Diseñar config management por entorno (development/LocalStack, staging/AWS, production/AWS) con Pydantic settings, validación, y secrets management
- ✅ Usar dependency injection para boto3 clients: inyectar clients configurados según el entorno, sin hardcodear endpoints en lógica de negocio
- ✅ Escribir tests que corran contra LocalStack Y AWS con el mismo test suite, usando feature flags para AWS-only features
- ✅ Implementar feature flags para servicios que no están disponibles en todos los entornos (SageMaker en AWS, no en LocalStack)
- ✅ Diseñar graceful degradation: si un servicio cloud no responde, la app degrada funcionalidad en lugar de crashear
- ✅ Documentar un migration runbook operativo que otro ingeniero pueda seguir paso a paso
- ✅ Producir una Migration-Ready AI App que corra contra LocalStack y AWS sin cambios de código
Objetivo profesional
Cuando un equipo de ingeniería dice "necesitamos migrar de staging a producción" o "vamos a agregar un entorno de QA", tú vas a saber exactamente qué hacer: config por entorno, clients inyectados, tests que verifican, feature flags para capacidades diferentes, y un runbook documentado. No es solo que tu app funcione — es que puedas operar la migración como un proceso repetible y verificable. Este es el skill que separa a un desarrollador de un ingeniero de producción.
Roadmap del Módulo
Mapa de cápsulas
| # | Cápsula | Qué aprenderás | Tipo |
|---|---|---|---|
| 01 | Introducción (esta) | Context, objetivos, setup, roadmap | Intro |
| 02 | Environment Abstraction | Abstraer endpoints y config para código agnóstico al entorno | Técnica |
| 03 | Config Management Multi-Entorno | Pydantic Settings, .env files, validación, secrets por entorno | Técnica |
| 04 | Dependency Injection boto3 Clients | Factory pattern, inyección de clients S3/Lambda configurados | Técnica |
| 05 | Testing Multi-Entorno | Pytest fixtures, conftest.py, tests contra LocalStack Y AWS | Técnica |
| 06 | Feature Flags Cloud | Habilitar/deshabilitar features por entorno, SageMaker only en AWS | Técnica |
| 07 | Graceful Degradation | Fallbacks, circuit breakers, health check con niveles de degradación | Técnica |
| 08 | Proyecto: Migration-Ready AI App | App AI migration-ready con abstraction layers, tests, runbook | Proyecto |
Flujo de aprendizaje
Primero entenderás environment abstraction (cápsula 02): cómo abstraer endpoints y configuración para que el código no sepa si habla con LocalStack o AWS. Luego implementarás config management estructurado (cápsula 03): Pydantic settings, archivos .env por entorno, validación, y secrets management. Después usarás dependency injection (cápsula 04) para crear boto3 clients configurados con un factory pattern — la lógica de negocio recibe clients listos, no los construye. Con la infraestructura de config y clients lista, escribirás tests multi-entorno (cápsula 05): mismo test suite, diferentes backends, con fixtures que detectan el entorno. Implementarás feature flags (cápsula 06) para manejar servicios que solo existen en ciertos entornos (SageMaker en AWS, no en LocalStack). Diseñarás graceful degradation (cápsula 07) para que la app no crashee si un servicio cloud no responde. Finalmente integrarás todo en una Migration-Ready AI App (cápsula 08).
La progresión es: abstracción → configuración → inyección → testing → feature flags → degradación → proyecto.
Duración estimada del módulo: 1.5-2 horas.
Conexión con el Proyecto
Proyecto de este módulo: Migration-Ready AI App
La Migration-Ready AI App es la app AI del Módulo 5 refactorizada con abstraction layers:
- Environment abstraction: endpoints y credenciales por config
- Config management: Pydantic settings con validación por entorno
- Dependency injection: factory crea boto3 clients según entorno
- Tests multi-entorno: mismo suite contra LocalStack y AWS
- Feature flags: SageMaker habilitado solo en AWS
- Graceful degradation: fallbacks si un servicio no responde
- Migration runbook: documento paso a paso para migrar
Migration-Ready AI App:
├── config/
│ ├── settings.py ← Pydantic Settings
│ ├── .env.local ← Config LocalStack
│ ├── .env.staging ← Config AWS staging
│ └── .env.production ← Config AWS producción
├── clients/
│ ├── factory.py ← Factory de boto3 clients
│ └── health.py ← Health checks
├── services/
│ ├── document_processor.py ← Lógica de negocio (agnóstica al entorno)
│ └── feature_flags.py ← Feature flags
├── tests/
│ ├── conftest.py ← Fixtures multi-entorno
│ ├── test_s3_operations.py
│ └── test_migration.py
├── migration/
│ └── RUNBOOK.md ← Migration runbook operativo
└── handler.py ← Lambda handler
Conexión con módulos anteriores y posteriores
Módulo 4: LocalStack → probaste S3 + Lambda localmente
↓
Módulo 5: AWS Services → profundizaste integración, IAM, costes
↓
Módulo 6: Migration Patterns → abstraes para que funcione en ambos ← ESTÁS AQUÍ
↓
Módulo 7: Alternative Platforms → la abstraction layer facilita evaluar alternativas
↓
Módulo 8: Proyecto Integrador → deploy a producción del artefacto migration-ready
La app migration-ready del M6 es el artefacto que se despliega en M8. Y la abstraction layer que construyes aquí facilita la evaluación de M7: si la decision matrix dice "Render en lugar de AWS," tu app migration-ready puede adaptarse porque la infraestructura está abstraída.
Prerequisitos
Lo que ya sabes
- ✅ S3 para AI assets — Organización, operaciones boto3, lifecycle (Módulo 5)
- ✅ Lambda para inferencia — Handler, retry, structured output (Módulos 3, 5)
- ✅ LocalStack — S3 y Lambda local, boto3 con endpoint_url (Módulo 4)
- ✅ IAM basics — Roles, policies, least privilege (Módulo 5)
- ✅ Docker Compose — Multi-container, services (Módulo 2)
- ✅ Python intermedio — Clases, async, manejo de errores, pydantic
- ✅ Apps AI — Has invocado LLMs desde código (OpenAI SDK)
Lo que aprenderás aquí (nuevo)
- Environment abstraction: código agnóstico al entorno con config switching
- Pydantic Settings: config management tipado con validación automática
- Factory pattern para boto3: inyección de clients configurados por entorno
- Testing multi-entorno: conftest.py con detección de entorno y feature flags
- Feature flags para cloud: habilitar/deshabilitar capacidades por entorno
- Graceful degradation: circuit breakers, fallbacks, health check degradado
- Migration runbook: documentación operativa paso a paso
Si te falta algo
| Te falta | Recurso recomendado |
|---|---|
| S3 y Lambda en AWS | Módulo 5 de esta guía |
| LocalStack | Módulo 4 de esta guía |
| Lambda fundamentals | Módulo 3 de esta guía |
| Docker Compose | Módulo 2 de esta guía |
| Python + FastAPI | Python REST APIs for AI Guide — NIEVA |
| Apps AI | AI Engineering Bootcamp — NIEVA |
Setup Técnico
Herramientas necesarias
# Python 3.10+ (mismo que módulos anteriores)
python --version
# Dependencias del módulo
pip install boto3 pydantic pydantic-settings python-dotenv pytest
# Verificar
python -c "from pydantic_settings import BaseSettings; print('pydantic-settings OK')"
python -c "import boto3; print(f'boto3 {boto3.__version__} OK')"
python -c "import pytest; print(f'pytest {pytest.__version__} OK')"
# Docker y LocalStack (del M4)
docker --version
docker run -d --name localstack \
-p 4566:4566 \
-e SERVICES=s3,lambda,iam \
localstack/localstack
# AWS CLI
aws --version
Estructura del módulo
mkdir -p module-06/{config,clients,services,tests,migration}
cd module-06
# Estructura final
# module-06/
# ├── config/
# │ ├── settings.py # Pydantic Settings
# │ ├── .env.local # Config LocalStack
# │ ├── .env.staging # Config AWS staging
# │ └── .env.production # Config AWS producción
# ├── clients/
# │ ├── factory.py # Factory de boto3 clients
# │ └── health.py # Health checks
# ├── services/
# │ ├── document_processor.py # Lógica de negocio
# │ └── feature_flags.py # Feature flags
# ├── tests/
# │ ├── conftest.py # Fixtures multi-entorno
# │ ├── test_s3_operations.py
# │ └── test_migration.py
# ├── migration/
# │ └── RUNBOOK.md # Migration runbook
# └── handler.py # Lambda handler
Verificación rápida del entorno
import boto3
import os
def verify_environment():
"""Verifica que el entorno de desarrollo está listo."""
checks = {}
try:
s3 = boto3.client(
"s3",
endpoint_url="http://localhost:4566",
aws_access_key_id="test",
aws_secret_access_key="test",
region_name="us-east-1",
)
s3.list_buckets()
checks["localstack"] = "✅ Conectado"
except Exception as e:
checks["localstack"] = f"❌ {e}"
try:
from pydantic_settings import BaseSettings
checks["pydantic_settings"] = "✅ Instalado"
except ImportError:
checks["pydantic_settings"] = "❌ pip install pydantic-settings"
try:
import pytest
checks["pytest"] = "✅ Instalado"
except ImportError:
checks["pytest"] = "❌ pip install pytest"
for check, status in checks.items():
print(f" {check}: {status}")
return all("✅" in v for v in checks.values())
if verify_environment():
print("\nEntorno listo para el Módulo 6.")
else:
print("\nAlgunos componentes faltan. Revisa los errores arriba.")
Límites: Qué NO Cubre Este Módulo
- ❌ Multi-cloud — No migramos de AWS a GCP o Azure. El patrón de abstracción es similar, pero el scope es LocalStack → AWS.
- ❌ Infrastructure as Code — No usamos Terraform ni CDK. La migración es a nivel de código de aplicación, no de infraestructura declarativa.
- ❌ CI/CD pipelines — No configuramos pipelines de deployment. Eso es parte del Proyecto Integrador (M8).
- ❌ Kubernetes — No hay orquestación de containers. El foco es serverless (Lambda) y storage (S3).
- ❌ Service mesh — No hay Istio, Envoy, ni mallas de servicios. Es sobre-ingeniería para nuestro scope.
- ❌ Blue/green deployment — Estrategias de deployment avanzadas están fuera del scope. Aquí migramos config, no tráfico.
Qué sí cubrimos (y por qué)
| Tema | Razón |
|---|---|
| Environment abstraction | El código no debe saber en qué entorno corre |
| Config management | Configuración tipada, validada, y segura por entorno |
| Dependency injection | Clients de cloud inyectados, no construidos en lógica de negocio |
| Testing multi-entorno | Verificar que la migración funciona antes de ejecutarla |
| Feature flags | Manejar capacidades diferentes entre entornos |
| Graceful degradation | La app funciona (degradada) aunque un servicio falle |
Evidencia de Éxito
Al terminar este módulo, sabrás que tuviste éxito si:
- ✅ Tu app AI corre contra LocalStack con
ENVIRONMENT=localsin cambiar código - ✅ La misma app corre contra AWS con
ENVIRONMENT=awssin cambiar código - ✅ Tus tests pasan contra LocalStack Y contra AWS con el mismo test suite
- ✅ SageMaker se habilita solo cuando
ENVIRONMENT=aws(feature flag) - ✅ Si S3 no responde, la app retorna una respuesta degradada en vez de crashear
- ✅ Tienes un migration runbook que otro ingeniero puede seguir paso a paso
- ✅ Puedes agregar un nuevo entorno (ej:
ENVIRONMENT=qa) cambiando solo configuración
Test rápido de autoevaluación
Si puedes responder estas preguntas, vas por buen camino:
- ¿Cómo cambias tu app de LocalStack a AWS sin editar código fuente?
- ¿Qué pasa si tu app intenta usar SageMaker en LocalStack?
- ¿Cómo verificas que tu migración de LocalStack a AWS no rompió nada?
- ¿Qué hace tu app si S3 está caído temporalmente?
Resumen
- Este es el módulo más complejo de la guía — y el más valioso. Los patrones que aprendes aquí son los que usan los ingenieros senior para operar sistemas en producción real.
- Mismo código, cualquier entorno. Tu app no debe saber si corre en LocalStack, AWS staging, o AWS producción. La configuración decide, el código ejecuta.
- Migración como proceso, no evento. No es "aprieta un botón." Es un proceso con pasos, verificación, rollback. El runbook captura ese proceso.
- Testing como red de seguridad. La migración sin tests es un salto de fe. Con tests multi-entorno, es un proceso verificable y repetible.
- Los patrones son transferibles. Abstraction, config management, dependency injection, feature flags — aplican a cualquier cambio de infraestructura, no solo LocalStack → AWS.
- El código de este módulo se convierte en el artefacto del Proyecto Integrador (M8).
Recursos Adicionales
- The Twelve-Factor App — Config — Principios de configuración por entorno
- Pydantic Settings Management — Documentación oficial de Pydantic Settings
- Martin Fowler — Feature Toggles — Referencia sobre feature flags
- AWS Well-Architected — Reliability — Graceful degradation en AWS
- Microsoft — Circuit Breaker Pattern — Patrón circuit breaker
- LocalStack Documentation — Referencia de LocalStack
- Dependency Injection in Python — DI patterns en Python