AWS Desde la Perspectiva de un Solutions Architect: Teoría, Decisiones y Go

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.

Por Omar Flores

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

#aws #solutions-architecture #cloud-design #system-design #go #enterprise-architecture #trade-offs #aws-patterns