AWS Desde la Perspectiva de un Solutions Architect: Teoría, Decisiones y Go
Una guía teórica exhaustiva sobre AWS desde la mentalidad de un Solutions Architect: cómo pensar en decisiones arquitectónicas, trade-offs fundamentales, integración con Go y otros lenguajes, patrones de diseño empresarial, y cómo aplicar esto en proyectos reales.
AWS Desde la Perspectiva de un Solutions Architect: Teoría, Decisiones y Go
Cómo Pensar Como Arquitecto de Soluciones en AWS
🎯 Introducción: El Rol del Solutions Architect en AWS
¿Qué es un Solutions Architect?
Un Solutions Architect no es un programador. No es un DevOps engineer. No es un DBA. Es algo diferente.
Si un programador piensa: “¿Cómo código esto?”
Si un DevOps piensa: “¿Cómo despliego esto?”
Un Solutions Architect piensa: “¿Cuál es la decisión correcta para este problema de negocio?”
La diferencia es sutil pero fundamental. Un Solutions Architect debe entender:
- El problema de negocio (no solo técnico)
- Las restricciones (presupuesto, tiempo, equipo, compliance)
- Los trade-offs (qué ganas, qué pierdes)
- El horizonte temporal (MVP vs 5 años)
- Los riesgos (qué puede fallar, cuál es el plan B)
¿Por Qué AWS Específicamente?
AWS es la plataforma más compleja del mercado:
Azure tiene 200+ servicios
Google Cloud tiene 150+ servicios
AWS tiene 400+ servicios
Esta complejidad no es un bug, es un feature. Significa que:
✅ Hay una solución optimizada para casi cada caso de uso
✅ Tienes opciones (y con opciones vienen decisiones difíciles)
✅ No existe “una sola forma correcta”
✅ La arquitectura correcta depende del contexto
¿Por Qué Go en AWS?
Go es el lenguaje de infraestructura de AWS:
- Kubernetes: Escrito en Go
- Docker: Escrito en Go
- Terraform: Escrito en Go
- AWS CLI v2: Escrito en Go (parcialmente)
- etcd: Escrito en Go
Pero también es excelente para aplicaciones backend en AWS:
- Lambda: Go corre nativo (mejor que Java, comparable a Node)
- ECS/Fargate: Go compile a binarios pequeños y rápidos
- Microservicios: Go es perfecto para sistemas distribuidos
Lo Que Cubriremos en Esta Guía
Esta es una guía teórica pero práctica. No te daré código de “Hola Mundo”. Te daré:
✅ Modelos mentales de cómo pensar en AWS
✅ Frameworks de decisión para elegir servicios
✅ Trade-offs documentados con ejemplos reales
✅ Patrones arquitectónicos que escalan
✅ Integración con Go en diferentes contextos
✅ Casos de estudio de decisiones buenas y malas
🏗️ Parte 1: Los Tres Ejes de Toda Decisión Arquitectónica en AWS
Cuando eres un Solutions Architect, toda decisión arquitectónica tiene exactamente tres dimensiones. Ignorar una de ellas es un error.
Eje 1: Complejidad Operacional vs Flexibilidad Técnica
Este es el eje más importante y muchas veces el más ignorado.
Complejidad Operacional significa: ¿Cuánta infraestructura necesito mantener?
Ejemplo 1: S3
- Complejidad operacional: 0 (AWS lo maneja todo)
- Flexibilidad técnica: Limitada (es un bucket, punto)
Ejemplo 2: EC2
- Complejidad operacional: Muy alta (SO, patches, monitoring, scaling)
- Flexibilidad técnica: Total (es una máquina virtual, haz lo que quieras)
Ejemplo 3: RDS
- Complejidad operacional: Media (AWS maneja el DB, tú manejas backups, resizing)
- Flexibilidad técnica: Media (puedes configurar SQL, pero no acceso a filesystem)
La Decisión:
┌─────────────────────────────────────────────────────────┐
│ Si necesitas MÁXIMA FLEXIBILIDAD │
│ → Acepta COMPLEJIDAD OPERACIONAL alta │
│ (Ejemplo: EC2, self-managed Kubernetes) │
├─────────────────────────────────────────────────────────┤
│ Si necesitas MÍNIMA COMPLEJIDAD OPERACIONAL │
│ → Acepta FLEXIBILIDAD TÉCNICA limitada │
│ (Ejemplo: S3, Lambda, managed databases) │
├─────────────────────────────────────────────────────────┤
│ Si necesitas BALANCE (el caso más común) │
│ → Elige servicios MANAGED pero CONFIGURABLES │
│ (Ejemplo: ECS Fargate, RDS, AppConfig) │
└─────────────────────────────────────────────────────────┘
El Error Clásico:
Un startup pequeño con 2 engineers elige Kubernetes self-managed porque “es más flexible”. Resultado: 60% del tiempo de los engineers se gasta en mantener Kubernetes, 40% en features nuevas. Hubiera estado mejor con ECS Fargate (menos flexible, pero funciona).
Eje 2: Costo Actual vs Costo de Escalado
Este eje te mata silenciosamente si no lo manejas bien.
Costo Actual = Lo que pagas hoy
Costo de Escalado = Cómo cambia el costo cuando creces
Ejemplo 1: DynamoDB On-Demand
- Costo actual (100 requests/segundo): ~$50/mes
- Costo escalado (1000 requests/segundo): ~$500/mes
- Patrón: Lineal, predecible
Ejemplo 2: DynamoDB Provisioned
- Costo actual (100 requests/segundo): ~$30/mes
- Costo escalado (1000 requests/segundo): ~$300/mes
- Patrón: Lineal, pero más barato en escala
Ejemplo 3: S3 (storage)
- Costo actual (100 GB): ~$2/mes
- Costo escalado (10 TB): ~$230/mes
- Patrón: Lineal, predecible
Ejemplo 4: AWS Lambda
- Costo actual (1M invocations/mes): ~$0.20/mes
- Costo escalado (1B invocations/mes): ~$200/mes
- Patrón: Lineal, pero sorpresas por GB-seconds
La Decisión:
┌────────────────────────────────────────────────────────────┐
│ Si tu tráfico es IMPREDECIBLE (startup) │
│ → Elige servicios ON-DEMAND │
│ (DynamoDB On-Demand, Lambda, ALB) │
│ - Pagas solo lo que usas │
│ - Escalas automáticamente │
├────────────────────────────────────────────────────────────┤
│ Si tu tráfico es PREDECIBLE (empresa) │
│ → Elige servicios PROVISIONED + RESERVED CAPACITY │
│ (DynamoDB Provisioned, RDS Reserved Instances) │
│ - Pagas menos por GB │
│ - Necesitas forecasting │
├────────────────────────────────────────────────────────────┤
│ Si tu tráfico tiene PICOS PREDECIBLES │
│ → Elige servicios con AUTO-SCALING PREDICTIVO │
│ (ECS with predictive auto-scaling, Lambda concurrency) │
│ - Lo mejor de ambos mundos │
└────────────────────────────────────────────────────────────┘
El Error Clásico:
Una startup elige DynamoDB Provisioned “porque es más barato”. A los 3 meses, su tráfico crece 10x, no pueden cambiar rápido, y pagan 5x más que si hubiera usado On-Demand. Lección: costo actual ≠ costo total.
Eje 3: Homogeneidad Tecnológica vs Optimalidad por Caso
Este eje es sobre cuántos servicios diferentes debería usar.
Homogeneidad = Todo usa la misma tecnología
Optimalidad = Cada problema usa la tecnología correcta para ese problema
Ejemplo de Homogeneidad Extrema:
- Database: PostgreSQL (para TODO)
- User data ✅ (relacional, perfecto)
- Session storage ✅ (relacional, OK)
- Colas de trabajo ❌ (PostgreSQL no es cola, lento)
- Búsqueda full-text ❌ (PostgreSQL OK, pero no óptimo)
- Cache ❌ (PostgreSQL es disco, no memoria)
Ejemplo de Optimalidad Extrema:
- User data: PostgreSQL (relacional)
- Session: Redis (in-memory)
- Colas: SQS (purpose-built)
- Búsqueda: Elasticsearch (optimizado)
- Cache: Redis (in-memory)
- ¿Problema?: 5 systems para mantener
La Decisión:
┌──────────────────────────────────────────────────────────┐
│ STARTUP (< 10 people) │
│ → Homogeneidad. Usa PostgreSQL para todo. │
│ Razón: Mantenimiento es el killer, no performance │
├──────────────────────────────────────────────────────────┤
│ ESCALEUP (10-50 people) │
│ → Balance. PostgreSQL + Redis + SQS. │
│ Razón: Estos 3 resuelven 80% de casos │
├──────────────────────────────────────────────────────────┤
│ EMPRESA (50+ people) │
│ → Optimalidad. Cada problem su solución. │
│ Razón: Tienes equipo para mantener complexity │
└──────────────────────────────────────────────────────────┘
El Error Clásico:
Una empresa pequeña decides “necesitamos Elasticsearch, Cassandra, y Kafka porque Google los usa”. Resultado: 200 horas/año en mantenimiento de infraestructura, 0 en features nuevas. Deberían haber usado PostgreSQL + Redis.
🔄 Parte 2: El Framework de Decisión del Solutions Architect
Cuando un cliente llega a un Solutions Architect con un problema, la pregunta no es “¿Qué servicio de AWS uso?”. La pregunta es mucho más profunda.
Paso 1: Entender el Problema de Negocio Real
Cliente dice: "Necesitamos una API rápida"
Arquitecto pregunta: "¿Rápido para quién? ¿Y cómo mides rápido?"
Cliente dice: "Queremos escalar a 100 millones de usuarios"
Arquitecto pregunta: "¿Cuándo? ¿En 6 meses o 3 años?
¿Y qué pasa si no llegamos?"
El primer paso es desempaquetar la declaración de negocios para entender las restricciones reales:
Restricción 1: Tiempo
¿Cuándo necesita estar listo?
- MVP en 3 meses → Elige velocidad, no perfección
- Sistema para 10 años → Elige flexibilidad, no atajos
Restricción 2: Presupuesto
¿Cuál es el presupuesto?
- $1,000/mes → Serverless, zero ops
- $100,000/mes → Managed services con tunning
- $1,000,000/mes → Puedes hacer casi cualquier cosa
Restricción 3: Riesgo de Negocio
¿Qué pasa si se cae?
- "Si se cae, perdemos $10,000/hora" → Multi-region, HA
- "Si se cae, es inconveniente" → Single region OK
Restricción 4: Requisitos de Cumplimiento
¿Hay requisitos regulatorios?
- GDPR → Datos en EU
- HIPAA → Encryption, audit logs
- PCI → Isolated networks
- Ninguno → Máxima libertad
Paso 2: Mapear a Patrones Arquitectónicos Conocidos
Una vez entiendes las restricciones, mapeas a patrones que ya conoces.
Existen exactamente 6 patrones arquitectónicos principales en AWS:
Patrón 1: Monolito Escalable
Cliente → ALB → ECS Fargate (Auto-scaled) → RDS
Cuándo:
- Aplicación cohesiva (no queremos dividir)
- Equipo pequeño (5-10 engineers)
- Lógica interconectada
Ventajas:
- Operacionalmente simple
- Debugging fácil
- Deployment atómico
Desventajas:
- Escala limitada por bottleneck en el monolito
- Cambios pequeños requieren redeploy completo
Patrón 2: Microservicios Distribuidos
Cliente → API Gateway → Microservicios (ECS) → Databases variadas
↓
Async (SQS/Kinesis)
Cuándo:
- Equipos grandes (30+ engineers)
- Dominios claramente separados
- Requisitos de escala diferentes por servicio
Ventajas:
- Escalas independientes
- Equipos trabajan en paralelo
- Tech stack flexible por servicio
Desventajas:
- Complejidad operacional extrema
- Debugging distribuido es difícil
- Network latency
Patrón 3: Serverless Puro
Cliente → API Gateway → Lambda → DynamoDB
↓
CloudFront (static)
Cuándo:
- Tráfico bursty (picos impredecibles)
- Presupuesto muy limitado
- Cero interesse en ops
Ventajas:
- Zero ops
- Escalas automáticamente
- Pagas solo lo que usas
Desventajas:
- Cold starts
- Menos flexible
- Más caro si tráfico es constante
Patrón 4: Event-Driven Asincrónico
Productor → SQS/Kinesis/EventBridge → Consumidores (Lambda/ECS)
→ Data Lake (S3)
Cuándo:
- Workflow complejos
- Multiple consumers necesitan mismo evento
- Decoupling es crítico
Ventajas:
- Altamente desacoplado
- Fácil agregar nuevos consumers
- Durabilidad por defecto
Desventajas:
- Eventual consistency (no instant)
- Debugging distribuido
- Orquestación compleja (usa Step Functions)
Patrón 5: Edge Computing
User → CloudFront → Lambda@Edge → Origin (ECS/S3)
Cuándo:
- Latencia es crítica
- Content es geográficamente distribuido
- Transformación de request/response
Ventajas:
- Latencia baja global
- Caching inteligente
- Security en el edge
Desventajas:
- Limited Lambda capabilities en edge
- Debugging difícil
- Costos de data transfer
Patrón 6: Hybrid/On-Premises
Data Center → AWS Direct Connect → VPC → AWS Services
Cuándo:
- Migración gradual desde on-prem
- Requisitos de low latency
- Compliance requiere data local
Ventajas:
- Transición gradual
- Máximo control
- Latencia baja
Desventajas:
- Operacionalmente muy complejo
- Caro (Direct Connect, VPN)
- Debugging es nightmare
Paso 3: Elegir Servicios Específicos (Finalmente)
Solo después de mapear el patrón, eliges servicios específicos.
Ejemplo: Patrón de Microservicios
Pregunta: ¿Cuál es el compute?
Opciones: ECS, EKS, AppRunner, EC2
→ ECS Fargate si no necesitas K8s
→ EKS si ya usas K8s o necesitas específicamente eso
Pregunta: ¿Cómo se comunican?
Opciones: HTTP (service mesh), gRPC, async (SQS)
→ HTTP + service mesh si latency < 100ms importa
→ Async si decoupling > latency
Pregunta: ¿Qué database?
Opciones: RDS, DynamoDB, DocumentDB, ElastiCache
→ RDS si datos son relacionales
→ DynamoDB si acceso pattern es simple
→ DocumentDB si tienes documentos complejos
� Parte 3: Integración de Go en Patrones de AWS
Aquí es donde la teoría se encuentra con la práctica. Go es una opción única en AWS porque no es “un lenguaje más”. Es el lenguaje de infraestructura de AWS.
Pero eso no significa que Go sea siempre la opción correcta. La pregunta es: ¿Cuándo Go es óptimo en AWS?
Go vs Otros Lenguajes: El Análisis Real
Primero, una tabla comparativa:
┌─────────────┬──────────┬──────────┬────────┬─────────┬──────────┐
│ Lenguaje │ Lambda │ ECS │ Build │ Memoria │ StartUp │
│ │ Friendly │ Friendly │ Time │ Usage │ Time │
├─────────────┼──────────┼──────────┼────────┼─────────┼──────────┤
│ Go │ ⭐⭐⭐⭐⭐ │ ⭐⭐⭐⭐⭐ │ 1s │ 50MB │ 5ms │
│ Rust │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │ 30s │ 30MB │ 2ms │
│ Python │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │ 0.1s │ 100MB │ 50ms │
│ Node.js │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │ 0.5s │ 150MB │ 100ms │
│ Java │ ⭐⭐ │ ⭐⭐⭐ │ 10s │ 300MB │ 500ms │
│ C#/.NET │ ⭐⭐ │ ⭐⭐⭐ │ 5s │ 250MB │ 300ms │
│ Ruby │ ⭐⭐ │ ⭐⭐⭐ │ 0.2s │ 200MB │ 200ms │
└─────────────┴──────────┴──────────┴────────┴─────────┴──────────┘
Análisis:
- Go gana en Lambda porque: binario pequeño, fast startup, low memory
- Go gana en ECS porque: binarios tiny (1-100MB vs 500MB+ otros), scaling rápido
- Python/Node ganan en velocidad de desarrollo pero pierden en performance
Escenario 1: Lambda con Go
Pregunta fundamental: ¿Debería usar Go en Lambda?
Respuesta: Depende del patrón.
Sub-escenario 1A: API Gateway → Lambda (Request/Response)
Cliente HTTP → API Gateway → Lambda (Go) → RDS/DynamoDB → Response
Latency: 50-100ms (+ network)
Cold start impact: 5-10ms (Go, mínimo)
Decisión:
✅ USA GO SI:
- Necesitas < 100ms latency (API Response time matters)
- Invokes son frecuentes (cold starts no son problema)
- Costo es importante (pequeño binary = menor tiempo = menor costo)
❌ USA PYTHON/NODE SI:
- Latency no importa (usuarios pueden esperar)
- Desarrollar rápido > ejecutar rápido
- Team ya sabe Python, no sabe Go
Ejemplo Real:
Microservicio que procesa pagos en tiempo real:
→ USA GO (latency critical)
Batch job que corre 1x diaria:
→USA PYTHON (simplemente, no importa si tarda 2s vs 10ms)
Sub-escenario 1B: Event-Driven (SQS/Kinesis → Lambda)
SQS/Kinesis → Lambda (Go) → Process → DynamoDB
Latency: seconds OK (asincrónico)
Concurrency: 1,000+ invocations/segundo
Decisión:
✅ USA GO SI:
- Alto volumen de eventos (1000+ eventos/sec)
- Cada ms de latencia = costo (reserva menos concurrency)
- Procesamiento CPU-intensivo
❌ USA PYTHON/NODE SI:
- Volumen bajo (< 100 eventos/sec)
- Event processing simple
Ejemplo Real:
Sistema que procesa 10,000 eventos/segundo de IoT:
→ USA GO (memory/cpu efficient, less reserved concurrency needed)
Sistema que procesa 10 eventos/día de webhooks:
→ USA PYTHON (quien le importa si tarda 100ms vs 10ms)
Sub-escenario 1C: Cron Jobs / Scheduled Tasks
CloudWatch Events → Lambda (Go) → Data processing → S3
Runs: 1x per hour (fixed schedule)
Latency: doesn't matter at all
Decisión:
❌ NO USA GO:
- Cron jobs no tienen requisito de latencia
- Ejecutar en Python 100ms vs Go 5ms no importa
- Desarrollar en Go toma más tiempo
✅ USA PYTHON:
- Más rápido escribir
- Debugging más simple
- 100x mejor value
Escenario 2: ECS con Go
ECS es donde Go realmente brilla.
Cliente → ALB → ECS Fargate (Go containers)
↓
Autoscaling group
Por Qué Go en ECS Es Excelente
1. Tamaño de contenedor
Dockerfile (Java):
FROM openjdk:17
RUN apt-get install...
COPY app.jar .
ENTRYPOINT ["java", "-jar", "app.jar"]
Imagen resultante: 500MB
---
Dockerfile (Go):
FROM scratch
COPY app .
ENTRYPOINT ["./app"]
Imagen resultante: 15MB
Impacto:
- Menos tiempo pulling image (más rápido escalar)
- Menos storage en ECR
- Menos network traffic (importa en autoscaling)
2. Memoria
Java process: 300MB
Go process: 30MB
Con AWS Fargate, pagas por memoria:
Java: 512MB × $0.0000443/segundo × 2,592,000 (mes) = $57/mes per task
Go: 64MB × $0.0000443/segundo × 2,592,000 (mes) = $7.30/mes per task
Ahorro: 87% por task
Con 100 tasks simultáneas:
Java: $5,700/mes
Go: $730/mes
Diferencia: $4,970/mes = $59,640/año
3. Cold Start en Scaling
Cuando autoscaler agrega un nuevo task:
Go:
1. Pull image (15MB) = 1-2 segundos
2. Start container = 100ms
3. Ready to receive traffic = 2-3s total
Java:
1. Pull image (500MB) = 10-15 segundos
2. Start JVM = 1-2 segundos
3. Load classes = 3-5 segundos
4. Ready = 15-20s total
Durante un spike:
Tráfico sube de 100 req/s a 1000 req/s
Autoscaler agrega 10 tasks
Go: Listos en 3s (bueno)
Java: Listos en 20s (muchas solicitudes se descartan en timeout)
Decisión: ¿Go en ECS?
✅ USA GO SI:
- Tráfico bursty (spikes impredecibles)
- Autoscaling es crítico
- Presupuesto es apretado
- Performance importa
❌ USA OTROS SI:
- Tráfico estable (sin spikes)
- Task count es constante
- Presupuesto no es restricción
- Team no sabe Go
Escenario 3: EC2 con Go
EC2 es “máquina virtual”, así que cualquier lenguaje funciona.
Pero la pregunta es: ¿por qué EC2?
Cuándo EC2 Es la Opción
✅ USA EC2 SI:
- Necesitas licencias específicas (Microsoft SQL Server)
- Necesitas GPU/specialized hardware
- Estás migrando desde on-prem
- Tienes compromisos ya con hardware específico
❌ USA ECS/Lambda SI:
- No tienes restricción de SO
- Quieres managed services
Si ya estás en EC2 (por cualquier razón), Go es excelente porque:
- Compilas a binario → No necesitas runtime
- Puedes correr en cualquier Linux
- Pequeño → Bajo overhead en SO
Escenario 4: Microservicios Políglotas Con Go
Este es el patrón más realista en empresas.
API Gateway → Service Mesh →
├─ Go (backend core logic) ← Fast, efficient
├─ Python (ML/data science) ← Easy to write
├─ Node.js (real-time features) ← Async/WebSocket
└─ Java (legacy, enterprise) ← Already exists
Decisión: Qué servicio va dónde?
Servicio 1: User Auth & Core API
- Traffic: High
- Latency requirement: < 100ms
- Language: GO
- Reasoning: High throughput, low latency
Servicio 2: Payment Processing
- Traffic: Medium-High
- Latency: < 500ms (can queue)
- Language: GO or Python
- Reasoning: Go if throughput critical, Python if ease > performance
Servicio 3: ML/Recommendations
- Traffic: Low (runs in background)
- Latency: Doesn’t matter (async)
- Language: Python
- Reasoning: ML libraries, data science tools
Servicio 4: Real-time Notifications
- Traffic: Medium (WebSocket connections)
- Latency: < 50ms (user experience)
- Language: Node.js or Go
- Reasoning: Node good for connections, Go good for throughput
Servicio 5: Scheduled Reports
- Traffic: N/A (scheduled)
- Latency: Doesn’t matter
- Language: Python or Go
- Reasoning: Python = simpler, Go = no dependencies
El Trade-Off Final de Go en AWS
┌────────────────────────────────────────────────────────┐
│ VENTAJAS DE GO EN AWS │
├────────────────────────────────────────────────────────┤
│ ✅ Performance: 10-100x mejor que Python │
│ ✅ Binary size: 15MB vs 500MB (Java) │
│ ✅ Memory: 30MB vs 300MB (Java) │
│ ✅ Cold start: 5ms vs 500ms (Java) │
│ ✅ Cost: 70-80% menos que Java/C# │
│ ✅ Deployment: Binario único, sin runtime │
│ ✅ Concurrency: Goroutines para parallelism │
├────────────────────────────────────────────────────────┤
│ DESVENTAJAS DE GO EN AWS │
├────────────────────────────────────────────────────────┤
│ ❌ Time-to-market: Más lento escribir que Python │
│ ❌ Ecosystem: Menos librerías que Python/Node │
│ ❌ Learning curve: Más difícil que Python │
│ ❌ DevOps: Menos herramientas que Java (Kubernetes) │
│ ❌ Team velocity: Equipo Python puede ir 2x más rápido│
├────────────────────────────────────────────────────────┤
│ DECISIÓN FINAL: CUÁNDO USA GO │
├────────────────────────────────────────────────────────┤
│ │
│ USA GO SI CUALQUIERA DE ESTO ES VERDAD: │
│ • Performance es crítico (< 100ms latency) │
│ • Costo es restricción crítica │
│ • Autoscaling bursty es patrón │
│ • Tienes equipo Go ya │
│ • Es parte de infraestructura (CLI tools, etc) │
│ │
│ NO USES GO SI: │
│ • Time-to-market es más importante que cost │
│ • Performance no es restricción │
│ • Equipo solo sabe Python/JavaScript │
│ • Necesitas AI/ML/data science (Python wins) │
│ │
└────────────────────────────────────────────────────────┘
⚠️ Parte 4: Anti-patrones de Solutions Architects en AWS
Los anti-patrones son decisiones arquitectónicas que parecen correctas en el momento, pero destruyen el proyecto después.
El problema es que no se ven como malas decisiones hasta 6-12 meses después, cuando el costo es ya muy alto para cambiar.
Anti-patrón 1: “Necesitamos Kubernetes (EKS)”
La narrativa:
PM: "Queremos ser 'cloud-native' y usar Kubernetes"
DevOps: "Kubernetes es el estándar de la industria"
Arquitecto (débil): "OK, usamos EKS"
6 meses después:
- 2 engineers dedican 50% del tiempo a Kubernetes
- CI/CD con Kubernetes es 10x más complejo
- Debugging de problemas de network es un nightmare
- Presupuesto se fue a $200k/mes (era $50k proyectado)
- Product velocity: bajó 50%
Por qué es un anti-patrón:
✅ KUBERNETES ES CORRECTO SI:
- Tienes 50+ microservicios
- Necesitas multi-cloud portability
- Tienes team dedicated de 5+ DevOps engineers
- Escala es más importante que simplicity
❌ KUBERNETES ES MALO SI:
- Tienes < 20 microservicios
- Presupuesto < $500k/año
- Team < 50 engineers
- Equipo no tiene experiencia en K8s
La realidad:
90% de startups que adoptan Kubernetes nunca necesitaban Kubernetes. Necesitaban:
- Better deployment (ECS Fargate resuelve esto)
- Better monitoring (CloudWatch/X-Ray resuelven esto)
- Better scaling (ALB + autoscaling resuelve esto)
La decisión correcta:
Startup/Escaleup → ECS Fargate (managed K8s para los pobres)
Enterprise → EKS (si realmente necesitas K8s)
Costo de la mala decisión:
Presupuesto de Kubernetes por año:
- Infrastructure (EKS + worker nodes): $60k
- DevOps engineers (1.5 FTE): $180k
- Tools/monitoring: $10k
Total: $250k/año
Si hubieras usado ECS Fargate:
- Infrastructure: $30k
- DevOps engineers (0.25 FTE): $30k
- Total: $60k/año
Diferencia: $190k/año = dinero que no gastaste en features
Anti-patrón 2: “Cada Team Su Propia Database”
La narrativa:
Arquitecto: "Microservicios = cada servicio su database"
Team A: "Queremos MongoDB"
Team B: "Queremos PostgreSQL"
Team C: "Queremos Cassandra"
6 meses después:
- Queremos compartir un usuario entre servicios
- No podemos hacer join entre databases
- Sincronización es un caos
- Debugging es imposible
Por qué es un anti-patrón:
Database per service es correcto SI:
- Database size es diferente por servicio (1TB vs 100GB)
- Access patterns son radicalmente diferentes
- Escalado es independiente
- Equipos son completamente separados
Es MALO SI:
- Hay shared entities (usuarios, productos, etc.)
- Necesitas transacciones cross-service
- Equipos colaboran frecuentemente
La realidad:
95% de casos de “database per service” podrían usar una sola PostgreSQL y estar mejor.
La decisión correcta:
Patrón CORRECTO (95% de casos):
┌─────────────────────────────────────┐
│ PostgreSQL (shared database) │
│ │
│ Schemas: │
│ - public.users │
│ - service_a.tables │
│ - service_b.tables │
│ │
│ Todos leen/escriben en PostgreSQL │
│ Transacciones posibles │
│ Joins posibles │
│ Debugging es simple │
└─────────────────────────────────────┘
Patrón ALTERNATIVO (5% de casos, cuando realmente necesitas):
┌─────────────────────────────────────┐
│ Service A: PostgreSQL (relational) │
│ Service B: DynamoDB (simple access) │
│ Service C: Elasticsearch (search) │
│ │
│ Sincronización vía SQS/Kinesis │
│ Eventual consistency │
│ Más complejo, pero justified │
└─────────────────────────────────────┘
Anti-patrón 3: “Vamos a Escalar a 1 Millón de Usuarios”
La narrativa:
Founder: "Google y Facebook usan X, nosotros también"
Arquitecto: "Necesitamos arquitectura que escale a 1M usuarios"
Team: "Implementamos el sistema más complejo"
Realidad:
- 10,000 usuarios en el año 1
- 50,000 usuarios en el año 2
- Pero gastamos como si tuviéramos 1M
Resultado:
- Presupuesto inflado
- Complejidad innecesaria
- Velocity lenta
Por qué es un anti-patrón:
Overengineering para "futura escala" causa:
1. Presupuesto 10x más alto de lo necesario
2. Tiempo-to-market 2x más lento
3. Debugging 5x más complejo
4. Team atrapado en infraestructura, no features
La decisión correcta:
┌──────────────────────────────────────────────────────┐
│ ESCALAR CUANDO NECESITES ESCALAR │
│ │
│ Fase 1 (0-100k usuarios): │
│ - Simple monolito en ECS Fargate │
│ - Single RDS database │
│ - Costo: ~$2k/mes │
│ │
│ Fase 2 (100k-1M usuarios): │
│ - Dividir en microservicios si necesario │
│ - Add caching (ElastiCache) │
│ - Add read replicas si DB es bottleneck │
│ - Costo: ~$20k/mes │
│ │
│ Fase 3 (1M+ usuarios): │
│ - DynamoDB si tráfico es extremo │
│ - Multi-region si latency es crítico │
│ - Event-driven si decoupling es necesario │
│ - Costo: ~$200k+/mes │
│ │
│ 🎯 KEY: Escala cuando llegues a ese punto, │
│ no 2 años antes │
└──────────────────────────────────────────────────────┘
Anti-patrón 4: “Serverless Para Todo”
La narrativa:
Arquitecto enthusiast: "Serverless es el futuro, cero ops!"
Team: "Usamos Lambda para todo"
Realidad después de 3 meses:
- Lambda cost: $2,000/mes (era $200 proyectado)
- Cold starts hacen que API sea lento
- Debugging distribuido es pesadilla
- 15 minutos timeout es muy corto para ciertos jobs
Por qué es un anti-patrón:
Serverless es correcto SI:
- Tráfico es bursty (picos impredecibles)
- Workload es stateless
- Tolerancia a cold starts (o son raros)
- Costo total es menor que alternativas
Es MALO SI:
- Tráfico es steady/predecible
- Necesitas warm containers
- Timeout de 15 minutos no es suficiente
- Costo es más alto que ECS
La realidad:
AWS Pricing Calculator (100k requests/mes, 512MB memory, 5s duration):
Lambda:
- $0.20 per 1M requests = $20/mes
- $0.0000166667 per GB-second = $400/mes (OUCH!)
- Total: $420/mes
ECS Fargate (single task, always on):
- 1 vCPU, 2GB RAM = $30/mes
- Total: $30/mes
Diferencia: 14x más caro en Lambda
La decisión correcta:
USA LAMBDA SI:
- Invokes son sporadic (< 1/segundo promedio)
- Tráfico bursty (10x spikes)
- Costo total es menor
USA ECS SI:
- Tráfico steady (> 1/segundo promedio)
- Necesitas warm containers
- Costo es restricción
Anti-patrón 5: “Compliance, Entonces Arquitectura Pesada”
La narrativa:
Compliance Officer: "Necesitamos HIPAA/PCI/GDPR"
Arquitecto (reactivo): "Entonces necesitamos:
- Multi-region
- Encrypted everything
- Air-gapped networks
- Hardware security modules
- Compliance monitoring
"
Resultado:
- Costo: $500k/año (era $50k)
- Complexity: 10x
- Time-to-market: +6 meses
Por qué es un anti-patrón:
Compliance != Complexity extrema
HIPAA requiere:
✅ Data encryption at rest
✅ Data encryption in transit
✅ Access controls (IAM)
✅ Audit logging
NO requiere:
❌ Multi-region
❌ HSM
❌ Air-gapped network
❌ Custom infrastructure
La realidad:
AWS proporciona compliance "gratis" en servicios managed:
RDS con encryption:
- Encryption at rest: ✅ (built-in)
- Encryption in transit: ✅ (SSL/TLS)
- Audit logging: ✅ (CloudTrail)
- Cost: $300/mes
Self-managed compliance:
- You build everything: $300k infrastructure + $100k/year ops
La decisión correcta:
Usar servicios MANAGED de AWS que vienen con compliance:
- RDS (not EC2 + manual DB)
- S3 with encryption (not EBS)
- Cognito (not self-managed auth)
- Secrets Manager (not hardcoded)
- CloudTrail (not manual logging)
Esto es 80% del trabajo de compliance, 5% del costo
Anti-patrón 6: “Arquitectura Perfecta Desde Día 1”
La narrativa:
Arquitecto: "Necesitamos diseñar esto perfectamente antes de implementar"
Team: "3 meses de diseño, 0 líneas de código"
Startup: "Dinero se acaba mientras diseñamos"
Resultado:
- Se corre dinero antes de tener MVP
- Diseño es perfecto para problema que ya no existe
Por qué es un anti-patrón:
Arquitectura es viva, no estática.
Las cosas que cambiarán con 100% de certeza:
1. Requisitos del cliente (cambiarán 3x)
2. Volume/scale (nunca es lo que predijiste)
3. Technology stack (nuevas herramientas cada 2 años)
4. Team composition (personas se van, otras llegan)
5. Presupuesto (siempre less than needed)
La decisión correcta:
Arquitectura Ágil:
Mes 1:
- Diseñar simple monolito
- Deploy a AWS
- Get real users
- Real metrics
Mes 2-3:
- Recolectar data
- Identificar bottlenecks
- Iterative improvements
Mes 6+:
- Escalar según requisitos reales
- No proyecciones
🧭 Parte 5: Cómo Tomar Decisiones Como Solutions Architect
Cuando llega el momento de tomar una decisión arquitectónica importante en AWS, existe un checklist mental que los buenos arquitectos usan.
El Checklist de 5 Preguntas
Antes de elegir cualquier servicio de AWS, hazte estas 5 preguntas:
Pregunta 1: “¿Cuál es el requisito de negocio, no el técnico?”
Mala pregunta: "¿Usamos DynamoDB o PostgreSQL?"
Buena pregunta: "¿Cuál es el patrón de acceso a datos?"
Mala pregunta: "¿ECS o Lambda?"
Buena pregunta: "¿Es tráfico bursty o predecible?"
Pregunta 2: “¿Cuál es el costo hoy vs costo en 1 año?”
Calcula ambos:
Opción A (ECS):
- Hoy: $5k/mes
- En 1 año (10x crecimiento): $50k/mes
Opción B (Lambda):
- Hoy: $1k/mes (parece más barato)
- En 1 año: $100k/mes (OUCH!)
Decisión: ECS, aunque cuesta más hoy
Pregunta 3: “¿Qué puede salir mal?”
ECS posibles problemas:
- Container crash (solucionable con health checks)
- Database bottleneck (solucionable con read replicas)
- Network latency (solucionable con caching)
Lambda posibles problemas:
- Cold starts (no solution, inherent)
- Timeout limits (no solution, inherent)
- Cost explosion (no solution easy)
El que tiene "problems sin solución fácil" probablemente es malo
Pregunta 4: “¿Tiene nuestra team el expertise?”
Si elegimos Kubernetes:
- Do we have Kubernetes expert? NO
- How long to learn? 6 months
- Cost while learning? $200k (lost productivity)
- Risk? HIGH
Si elegimos ECS:
- Do we have ECS expert? Maybe someone has AWS
- Learning curve: 2 weeks
- Cost while learning: $20k
- Risk: LOW
Pregunta 5: “¿Puedo cambiar de opinión en 6 meses?”
Decisiones Reversibles (puedes cambiar):
- Language (Python → Go): Yes
- Compute (ECS → Lambda): Hard but possible
- Database (PostgreSQL → DynamoDB): Very hard
Decisiones No-Reversibles (stuck forever):
- Kubernetes adoption: Very hard to undo
- Multi-region: Hard and expensive to undo
- Custom infrastructure: Months to rewrite
El patrón:
✅ Elige decisiones reversibles cuando sea posible
❌ Evita decisiones no-reversibles
📊 Resumen: El Modelo Mental de Solutions Architect
Al final del día, el trabajo del Solutions Architect es traducir requisitos de negocio a decisiones de arquitectura optimales.
La Fórmula
Requisitos Negocio
+
Restricciones (Budget, Time, Team, Compliance)
+
Trade-offs (Costo vs Complejidad, Velocidad vs Escalabilidad)
=
Decisión Arquitectónica
Y esta decisión debe ser:
✅ Reversible (puedes cambiar de opinión)
✅ Documentada (otros entienden por qué)
✅ Monitoreable (sabes si fue correcta)
✅ Escalable (crece cuando lo necesites)
Las 3 Reglas de Oro
Regla 1: SIMPLE BEATS COMPLEX
Solución simple: Monolito en ECS
Solución compleja: Microservicios distribuidos con event mesh
Si ambas resuelven el problema, elige SIMPLE
Regla 2: MANAGED BEATS SELF-MANAGED
AWS RDS: Managed database
EC2 + Manual installation: Self-managed
Si ambas funcionan, elige MANAGED
Regla 3: CHEAPER TODAY > CHEAPER TOMORROW
Opción A: $5k/mes hoy, $50k/mes en 1 año
Opción B: $1k/mes hoy, $100k/mes en 1 año
Elige Opción A
🎓 Conclusión: Pensamiento de Solutions Architect
El cambio de mentalidad de programador a architect es radical.
Programador: "¿Cómo código esto?"
Architect: "¿Es esta la decisión correcta?"
Programador: "¿Qué framework uso?"
Architect: "¿Qué servicio AWS resuelve este problema?"
Programador: "¿Cómo optimizo performance?"
Architect: "¿Escala de forma económica?"
El trabajo del Solutions Architect es tomar decisiones que parecen “aburridas” pero salvan miles de dólares y meses de desarrollo.
Los mejores arquitectos no son los que eligen tecnología más cool. Son los que eligen la tecnología correcta para ese contexto específico. Y eso requiere entender no solo AWS, sino también:
- Negocio del cliente
- Restricciones reales
- Team capabilities
- Long-term vision
Cuando dominas esto, eres un Solutions Architect de verdad.
Tags
Artículos relacionados
Go CLI Apps: De 0 a Experto con Arquitectura Hexagonal
Guía completa para crear CLI apps profesionales en Go. Arquitectura hexagonal, goroutines, concurrencia, Linux y deployment.
Go Concurrente: Goroutines, Channels y Context - De Cero a Experto
Guía exhaustiva sobre programación concurrente en Go 1.25: goroutines, channels, context, patrones, race conditions, manejo de errores, y arquitectura profesional. Desde principiante absoluto hasta nivel experto con ejemplos prácticos.