Módulo 2: Common AI Architectures
AI-Specific Considerations
Descripción de la cápsula
Las cápsulas 02-05 cubrieron arquitecturas (monolito, microservicios, event-driven, híbridos) con énfasis AI-específico. Esta cápsula da un paso atrás y enfoca en consideraciones que son intrínsecamente de sistemas AI y afectan tu decisión arquitectónica transversalmente — independientemente del estilo que elijas. Son las cosas que un engineer construyendo "una API normal con un LLM pegado" pasaría por alto, pero que un engineer diseñando un sistema AI debe anticipar desde el primer ADR.
Cinco consideraciones críticas: cold start (cuando tu modelo o componente AI tarda 10-60s en estar listo después de un deploy o scale-up), context management distribuido (cómo mantener conversación o estado de usuario entre múltiples requests cuando el sistema es distribuido), costo de duplicar LLM calls (cuando microservicios independientes cada uno hacen su llamada al mismo LLM), GPU scheduling (recurso caro y escaso, requiere planning), y vector DB co-location (latencia entre tu API y tu vector DB importa más de lo que crees).
Cada una afecta cómo diseñas tu sistema. Ignorarlas conduce a sistemas que funcionan en demo pero fallan en producción, o que escalan mal, o que cuestan 3x más de lo necesario. Esta cápsula te da el vocabulario y los frameworks para anticiparlas en tus decisiones arquitectónicas.
Consideración 1: Cold start
El problema
En sistemas web tradicionales, cold start es típicamente <1 segundo: spin up de container, inicializar la app, listo. En sistemas AI, cold start puede ser dramáticamente más lento:
- Cargar modelo a memoria: 10-60 segundos para modelos pequeños, minutos para modelos grandes
- Inicializar vector DB connections: 100-500ms por connection, multiplicado por pool size
- Cargar embeddings cache en memoria: si tu sistema warm-loads embeddings frecuentes, segundos a minutos
- JIT compilation de modelos: PyTorch/TensorFlow optimizan en primera llamada, primer request es 5-10x más lento
Esto importa especialmente en:
- Serverless deployments: cada cold start es un problema (el primer request de cada nueva instancia espera)
- Auto-scaling: cuando agregas instancias por carga, las nuevas tardan en estar productivas
- Spot instances: si las usas para reducir costos, restart frecuentes = cold start frecuentes
Cómo afecta tu arquitectura
Si usas serverless (Lambda, Cloud Functions) para componentes AI: el cold start típico de 10-30s te va a doler. Para componentes user-facing, casi nunca es viable. Para batch processing async, puede funcionar.
Si auto-scaling es importante: necesitas warm pool de instancias o predictive scaling que arranca instancias antes de necesitarlas, no después. "Reactive scaling" responde demasiado lento.
Si usas modelos locales: la decisión de "auto-hostear" implica responsabilidad de manejar cold start. Modelos en API externa (OpenAI, Anthropic) no tienen este problema visible para ti.
Estrategias de mitigación
1. Always-on instances con minimum count: en lugar de scale-to-zero, mantén siempre 2+ instancias warm. Pagas baseline pero eliminas cold start para usuarios.
2. Pre-warming: durante deploy, hacer health checks que ejerciten model loading antes de marcar instancia como ready. Tarda 30s extra en deploy pero los usuarios no esperan.
3. Lazy loading con fallback: cargar modelos al primer uso, pero con timeout y fallback a otra instancia. Útil para componentes secundarios.
4. Provisioned concurrency en serverless: AWS Lambda y similares ofrecen "provisioned concurrency" que mantiene workers warm. Cuesta más pero elimina cold start.
5. Containers con images optimizadas: si tu container weighs 5GB porque incluye modelo, el download del image en startup ya es minutos. Usar shared model storage (mounts, S3 + cache) en lugar de embedding en image.
Ejemplo concreto
Sistema A: serverless puro con cold start de 25s.
- p50 latency cuando warm: 4s
- p99 latency: 30s (incluye cold starts de scale-up)
- UX: aceptable la mayor parte del tiempo, terrible 1% del tiempo
Sistema B: containers con minimum 3 instances, pre-warm en health checks.
- p50: 4s
- p99: 6s
- Costo: 30% más alto que serverless (3 instancias siempre on)
- UX: consistente
Para sistemas user-facing, el costo extra de B casi siempre se justifica.
Consideración 2: Context Management Distribuido
El problema
Las conversaciones AI tienen estado. Un usuario hace una pregunta, recibe respuesta, hace una pregunta de seguimiento que asume contexto previo ("¿y qué pasa si X?"). Tu sistema necesita acceder a la conversación previa para responder correctamente.
En un monolito esto es trivial: la conversación se carga de DB al inicio del request, se pasa al agent, se actualiza al final. Una sola transacción, sin distributed concerns.
En arquitecturas distribuidas se vuelve complicado:
- Microservicios: el Agent Service no tiene la conversación; debe leer de un Conversation Service. Latencia adicional por request, posible inconsistencia.
- Event-driven: la respuesta llega async; ¿cuál es la conversación cuando llega un message más nuevo antes de que respondas el anterior?
- Múltiples instancias: si user envía mensajes consecutivos a instancias distintas (load balancer), cada una debe coordinar para tener la versión actualizada.
Patrones de manejo
Pattern 1: Centralized state store
All services → Conversation Store (Redis/DynamoDB) → Single source of truth
- Simple conceptualmente
- Latencia adicional por request (read + write)
- Single point of failure si no es replicated
Pattern 2: Event-sourced conversations
Each message → Append-only event log → State derived by replay
- Auditable, replayable
- Más complejo de implementar
- Performance issue para conversations largas (replay caro)
Pattern 3: Session affinity (sticky sessions)
Load balancer → consistent hashing → User always to same instance
- Simple, instance has local state
- Problema si instance falla (session lost)
- No escala bien con muchos usuarios concurrentes
Pattern 4: Per-request context loading
Each request → Load context fresh → Process → Save
- Stateless services (escalan bien)
- Latencia adicional cada request
- Predominante en producción AI
Implicación para arquitectura
Si decides microservicios o multi-instancia, necesitas decidir desde diseño cómo manejarás context. No es feature que agregas después — es decisión arquitectónica que afecta a todos los componentes que tocan conversaciones.
Para sistemas AI con conversations multi-turn (chat, agents conversacionales):
- Si monolito + single instance: trivial, no problema
- Si monolito + multiple instances: necesitas centralized state (Redis/Postgres) leído por cada request
- Si microservicios: el Conversation Service es típico, accedido por todos los services que tocan conversations
- Si event-driven: necesitas decidir si los eventos incluyen full context o referencias a state externo
Costo de no planificar
He visto sistemas donde el equipo "decidió pensarlo después", terminó con cada microservicio cacheando conversations localmente, y los bugs por inconsistencia (usuario ve respuesta basada en context viejo) tomaron 3 meses para arreglar. Decisión arquitectónica desde el día 1, ahorra rework.
Consideración 3: Costo de Duplicar LLM Calls
El problema
Cada llamada al LLM cuesta. En un monolito, una request hace típicamente 1-3 llamadas al LLM. Si el flow es:
- Embed query (cheap, $0.0001)
- Generate response (expensive, $0.005-0.05)
Total: 1 llamada cara.
En microservicios mal diseñados, fácilmente terminas con duplicación:
- API Gateway valida con LLM (toxicity check) — 1 LLM call
- Query Service procesa con LLM — 1 LLM call
- Agent Service llama LLM internamente — 1 LLM call por step (3-5 steps)
- Eval Service evalúa con LLM-as-judge — 1 LLM call
Total: 6-10 LLM calls por request, cada una costando $0.005-0.05. Una sola request puede costar $0.05-0.50, vs $0.01 en monolito.
Cuándo se justifica
A veces múltiples LLM calls son necesarios:
- Multi-step agents: el agent legítimamente necesita varios reasoning steps
- Pre/post processing: moderation antes, eval después
- Different models for different tasks: classification con modelo barato, generation con modelo caro
Lo problemático es duplicación accidental: cada microservicio "por si acaso" hace su propia LLM call cuando podía reutilizar el resultado del anterior.
Patterns para evitar duplicación
1. Pass results through services, no recompute:
API → moderation result + content → Query Service → response → Eval Service
Cada servicio recibe lo que necesita del anterior, no recalcula.
2. Shared cache de LLM responses: Si dos servicios hacen el mismo prompt, deben hit cache (Redis) en lugar de duplicar.
3. Coordinator pattern: Un servicio orquestador hace todas las LLM calls coordinadamente, los demás reciben resultados.
4. Async aggregation con event-driven: Eval/analytics consumen events del request, no hacen LLM calls síncronas que duplican.
Costo concreto
Sistema con microservicios mal diseñados:
- 50k queries/día × 6 LLM calls/query = 300k LLM calls/día
- $0.005 promedio = $1,500/día = $45,000/mes
Sistema bien diseñado:
- 50k queries × 2 LLM calls/query = 100k calls/día
- $0.005 = $500/día = $15,000/mes
Diferencia de $30k/mes solo en LLM calls por elegir mal arquitectura. Esto es real, no teórico.
Consideración 4: GPU Scheduling
El problema
GPUs son recursos caros y escasos. En 2026:
- H100 (top tier): $2-5/hora en cloud, alta demanda, disponibilidad limitada
- A100: $1-2/hora, más disponible
- L4, T4: $0.50-1/hora, para inference más barato
Implicaciones:
1. No puedes "auto-scalear infinitamente": si tu sistema necesita GPUs y la región está sin stock, no hay nada que hacer.
2. Reservaciones vs on-demand: GPUs reservadas son 50-70% más baratas pero requieren commitment. Mal calibrado = pagas por GPUs que no usas.
3. GPU-bound vs CPU-bound mixing: si juntas componentes GPU y CPU en mismo servicio, GPU está idle parte del tiempo (caro) o CPU saturada (lento).
Implicación arquitectónica
Si usas modelos locales: separar el componente GPU del resto es casi siempre correcto. Embedding service en su propio servicio con GPU dedicada.
Si usas APIs externas (OpenAI, Anthropic): no tienes este problema visible — el provider maneja GPUs. Pero pagas un premium por esa abstracción.
Mixed approach: usar API para inference principal, modelo local para tareas específicas (embedding, classification) donde el costo per-call domina.
Decision framework
¿Modelo local o API?
├── Volumen alto (>1M calls/día) → considera local (potencial ahorro)
├── Volumen bajo (<10k/día) → API casi siempre mejor
└── Volumen medio (10k-1M/día) → analiza costo total ownership
Si local:
├── Component dedicado GPU (microservicio)
├── Reservas de GPU si volumen estable
└── Plan de fallback si GPU stock outage
Consideración 5: Vector DB Co-location
El problema
Vector DB queries son rápidas (50-200ms para top-k similar) si la network es rápida. Si tu API y vector DB están en regiones distintas, la latencia adicional puede dominar:
- Same region, same VPC: 1-5ms network overhead
- Same region, different VPC: 5-15ms
- Cross-region: 50-150ms
- Cross-cloud (AWS API → Pinecone managed): 20-50ms
Para un sistema con flow:
- Cache check (Redis): 5ms
- Vector search: 100ms
- LLM call: 5,000ms
- Response: 10ms
Total: 5,115ms
Si vector search agrega 100ms por mala co-location:
- Cache check: 5ms
- Vector search: 200ms (100ms query + 100ms network)
- LLM call: 5,000ms
- Response: 10ms
Total: 5,215ms — 100ms adicional, casi 2% del flow.
Suena poco, pero a 50k queries/día son 5,000 segundos diarios desperdiciados en network avoidable.
Implicación arquitectónica
Decisión de provider: si usas Pinecone (managed, US-East), tu API ideal está en us-east-1. Si está en us-west-1, agregas latencia gratis.
Decisión de hosting: self-hosted vector DB co-located con tu API tiene mejor latencia que managed cross-region. Trade-off entre latencia y operational overhead.
Decisión multi-region: si tu API es multi-region, considera vector DB multi-region o accept latencia adicional para regions secundarias.
Frameworks de decisión
Vector DB choice:
├── Performance crítico (<100ms p99 vector search) → co-locate
│ ├── Self-hosted en mismo VPC
│ └── Managed con peering de region
└── Performance no crítico → managed cualquier región
└── Latencia 20-50ms aceptable
Caso desarrollado: aplicar las 5 consideraciones
Sistema: AI Knowledge Assistant escalado (50k queries/día, 12 engineers, $5k/mes budget cloud, US users).
Análisis
Cold start:
- API en containers con 3 instances minimum, no serverless. Healthchecks ejercitan model loading.
- Embedding Worker en queue model (consumer pattern), tolerante a startup time.
Context management:
- Conversations en Postgres (centralized). Cache de últimas 10 conversations en Redis para hot path.
- Cada request lee fresh, escribe al final. Stateless services.
LLM call duplication:
- Coordinator pattern: API hace una LLM call por request en general flow. Agent puede hacer 3-5 si tool use.
- Eval async via event bus, evita LLM calls duplicadas síncronas.
- Cache de LLM responses para queries idénticos (Redis con 24h TTL).
GPU scheduling:
- LLM via Anthropic API (no GPU local).
- Embeddings via Anthropic (no GPU local).
- Embedding Worker es CPU-bound (recibe response del API, hace processing).
- No tenemos GPU bottleneck — beneficio de usar APIs.
Vector DB co-location:
- Pinecone managed en us-east-1.
- API en AWS us-east-1.
- Latencia network: ~5-10ms (cross-VPC same region, peering).
Decisión final
Arquitectura:
- API monolítica en us-east-1 con 3-5 instances
- Embedding Worker como microservicio (procesamiento batch async)
- Integration Service como microservicio (Slack/Discord)
- Conversations en Postgres + Redis cache
- LLM via Anthropic API (no GPU local)
- Pinecone us-east-1 (co-located)
Costo proyectado:
- Compute: $1,500/mes (containers + workers)
- LLM: $1,500/mes (50k × $0.001 promedio with caching)
- Pinecone: $560/mes
- Postgres + Redis: $200/mes
- Otros (logging, monitoring): $300/mes
Total: ~$4,060/mes — dentro de presupuesto $5k/mes.
Trampas y errores comunes
Error 1: Asumir que serverless es "siempre mejor para cost"
Serverless suena ideal por scale-to-zero. Para componentes AI con cold start de 30s, scale-to-zero significa terrible UX. El "ahorro" se compensa con calidad de servicio degradada.
Cómo detectarlo: ¿propones serverless para componentes user-facing AI sin medir cold start?
Cómo corregir: medir cold start del componente. Si >5s, serverless solo viable con provisioned concurrency (que elimina ahorro de scale-to-zero).
Error 2: Context cacheado por instance sin coordinación
Cada instance del API mantiene cache local de conversations. Cuando user va a otra instance, el cache es stale. Bugs raros, difíciles de debug.
Cómo detectarlo: ¿tu sistema tiene multiple instances + per-instance caches sin invalidation cross-instance?
Cómo corregir: centraliza state crítico en Redis/Postgres. Caches locales solo para datos read-only o regenerable.
Error 3: LLM call por servicio "porque es modular"
Engineer extrae cada componente a microservicio y cada uno hace su LLM call para "ser modular". El costo se 5x sin beneficio.
Cómo detectarlo: ¿cuántas LLM calls por request en producción? Si >3 sin razón explícita (multi-step agent, eval), hay duplicación.
Cómo corregir: coordinator pattern. Un servicio hace LLM calls, los demás reciben resultados.
Error 4: GPU local "porque modelos son caros"
Engineer calcula "OpenAI cuesta $1k/mes vs GPU H100 cuesta $200/mes" y propone modelo local. Olvida: ops overhead, cold start, GPU stock outages, calidad menor del modelo open source.
Cómo detectarlo: ¿la decisión de "local vs API" considera total ownership cost o solo precio del compute?
Cómo corregir: TCO incluye dev hours, ops, infra, model evaluation, fallback. Para volumen <1M calls/día, API casi siempre gana en TCO.
Error 5: Vector DB en otra región "porque es mejor proveedor"
Engineer elige vector DB de mejor calidad en otra región. Latencia adicional 50-100ms se acumula, p99 sufre.
Cómo detectarlo: ¿la decisión de vector DB considera región y latencia o solo features?
Cómo corregir: features pesan, pero co-location también. Diferencia entre top-tier vector DB en mala región y segundo-tier en buena región puede ser pequeña en calidad pero grande en latencia.
Auto-verificación
Para un sistema AI que conozcas (real o hipotético), evalúa cómo manejas las 5 consideraciones:
| Consideración | Tu approach | ¿Es óptimo? |
|---|---|---|
| Cold start | ? | ? |
| Context management | ? | ? |
| LLM call duplication | ? | ? |
| GPU scheduling | ? | ? |
| Vector DB co-location | ? | ? |
Si alguno no está claro o la respuesta es "no lo había pensado", esa es una decisión arquitectónica pendiente que merece investigation antes de construir más.
Ver caso ejemplo (Q&A interno escalado)
| Consideración | Tu approach | ¿Es óptimo? |
|---|---|---|
| Cold start | 3+ instances minimum, pre-warm en healthcheck | ✅ Óptimo para user-facing |
| Context management | Postgres + Redis cache, stateless services | ✅ Estándar industria |
| LLM call duplication | Coordinator pattern + Redis cache + async evals | ✅ Minimiza duplication |
| GPU scheduling | API external (no GPU local) | ✅ Para volumen 50k/día, justified |
| Vector DB co-location | Pinecone us-east-1 + API us-east-1 | ✅ ~5ms network overhead |
Sistema bien optimizado en las 5 dimensiones. Posibles mejoras: si volumen sube a 5M+/day, evaluar embedding local (ahorro vs API).
Resumen y siguiente paso
En esta cápsula viste 5 consideraciones AI-específicas que afectan tu arquitectura transversalmente:
- Cold start: 10-60s típico en AI, requiere always-on instances o provisioned concurrency
- Context management distribuido: requiere decisión desde diseño (centralized vs event-sourced vs sticky session vs per-request)
- Costo de duplicar LLM calls: monitor LLM calls per request, usar coordinator pattern, async para evals/analytics
- GPU scheduling: APIs externas eliminan complexity para muchos casos; modelos locales solo si volumen justifica
- Vector DB co-location: misma región/VPC importa; cross-region puede agregar 50-100ms
Cada una afecta decisiones arquitectónicas en cualquier estilo (monolito, microservicios, event-driven, híbrido). Anticiparlas desde el primer ADR ahorra rework caro después.
Antes de avanzar a la cápsula 07, deberías poder:
- Identificar las 5 consideraciones AI-específicas y por qué cada una importa
- Calcular el costo de cold start o LLM duplication en un sistema dado
- Decidir entre modelo local y API basado en TCO, no solo compute
- Aplicar context management pattern apropiado a tu arquitectura
En la cápsula 07 — Decision Framework para elegir arquitectura — vas a sintetizar todo lo aprendido en M02 en un framework aplicable mecánicamente. Vas a tener una matriz de decisión con criterios, pesos, scores que aplica a cualquier sistema AI. Esa matriz no reemplaza juicio — lo estructura. Te permite presentar a un equipo o stakeholder el razonamiento detrás de tu recomendación arquitectónica con rigor. Y te prepara para el proyecto de la cápsula 08, donde aplicarás todo en un Architecture Comparison Document completo.
Recursos
- The Cold Start Problem in Serverless — AWS guide sobre cold start patterns
- Designing Distributed Systems — Brendan Burns — Patterns para state management distribuido
- Pinecone Architecture Best Practices — Documentation oficial sobre co-location
- GPU Pricing — AWS Reserved Instances — Pricing y reservations para planeación de GPU
- LLM Cost Optimization — OpenAI Cookbook — Patterns para reducir costo de LLM calls
- Database Per Service — Microservices.io — Pattern para state management en microservices