Módulo 1: Understanding Deployment Options
6. Decision Matrix Framework
Descripción
En esta cápsula vas a construir el framework que convierte análisis de trade-offs en una decisión documentada y defendible. La decision matrix no es un ejercicio académico — es la herramienta que produces en el proyecto del módulo y que reutilizas en los Módulos 7 y 8. Al terminar, tendrás un template funcional y sabrás cómo llenarlo para cualquier caso de uso.
Contexto: Las cápsulas anteriores te dieron los inputs: categorías de deployment, trade-offs en 5 dimensiones, comparación serverless vs containers, y cost modeling. Esta cápsula te da la estructura para sintetizar todo en una decisión.
Qué Es una Decision Matrix
Definición
Una decision matrix es una tabla que evalúa opciones contra criterios ponderados, produciendo un score numérico que indica cuál opción se alinea mejor con tus requirements. No reemplaza el juicio — lo estructura.
Decision Matrix = Criterios + Pesos + Evaluación + Score
Criterios: Las dimensiones que importan para tu caso
Pesos: La importancia relativa de cada criterio (suman 100)
Evaluación: Score de cada opción en cada criterio (1-5)
Score: Peso × Evaluación, sumado por opción
Por qué funciona para deployment
Sin matrix, las decisiones de deployment son: "mi amigo usa Railway" o "AWS es lo que usan las empresas serias." Con matrix, la decisión es: "dado mis constraints de presupuesto, equipo, y tráfico, Railway tiene un score de 4.2 vs AWS con 3.1 — y puedo explicar por qué."
La matrix es especialmente valiosa cuando:
- Tienes que justificar la decisión ante un equipo o manager
- Necesitas re-evaluar cuando cambian las condiciones
- Quieres documentar el razonamiento para tu yo futuro
Anatomía de una Decision Matrix
Estructura completa
# Decision Matrix: [Nombre del proyecto]
## Contexto
- Proyecto: [Qué app AI]
- Stage: [MVP / Growth / Scale]
- Equipo: [Tamaño y skills]
- Presupuesto: [Rango mensual]
- Timeline: [Urgencia]
## Criterios y Pesos
| # | Criterio | Peso | Justificación del peso |
|---|----------|------|----------------------|
| 1 | Coste mensual | 25 | Presupuesto limitado, <$50/mes |
| 2 | Complejidad operativa | 20 | Equipo de 1, no puedo dedicar >2hrs/semana |
| 3 | Time-to-deploy | 20 | Necesito MVP online esta semana |
| 4 | Escalabilidad | 15 | Crecimiento esperado pero no urgente |
| 5 | Control | 10 | Sin requirements de compliance |
| 6 | AI-specific (cold starts, streaming) | 10 | Chat con streaming es feature clave |
| **Total** | | **100** | |
## Evaluación (1-5, donde 5 = mejor)
| Criterio (Peso) | Local | Serverless | Managed | Self-hosted |
|-----------------|:-----:|:----------:|:-------:|:-----------:|
| Coste (25) | 4 | 5 | 4 | 1 |
| Complejidad (20) | 3 | 4 | 5 | 1 |
| Time-to-deploy (20) | 3 | 4 | 5 | 1 |
| Escalabilidad (15) | 2 | 5 | 3 | 4 |
| Control (10) | 4 | 2 | 3 | 5 |
| AI-specific (10) | 5 | 2 | 4 | 5 |
## Scores Ponderados
| Criterio | Local | Serverless | Managed | Self-hosted |
|----------|:-----:|:----------:|:-------:|:-----------:|
| Coste | 100 | 125 | 100 | 25 |
| Complejidad | 60 | 80 | 100 | 20 |
| Time-to-deploy | 60 | 80 | 100 | 20 |
| Escalabilidad | 30 | 75 | 45 | 60 |
| Control | 40 | 20 | 30 | 50 |
| AI-specific | 50 | 20 | 40 | 50 |
| **TOTAL** | **340** | **400** | **415** | **225** |
## Decisión
- **Recomendación:** Managed (Railway) — Score 415
- **Segunda opción:** Serverless (Lambda) — Score 400
- **Descartados:** Self-hosted (Score 225, overkill para el caso)
## Condiciones de re-evaluación
- Si tráfico > 500 req/hora → re-evaluar serverless vs managed
- Si necesito streaming → confirmar que managed lo soporta bien
- Si presupuesto > $200/mes → considerar local (VPS) para más control
- Review programado: 3 meses después del deploy
Paso a Paso: Cómo Construir Tu Matrix
Paso 1: Define el contexto
Antes de evaluar opciones, documenta tu situación. Sin contexto, los criterios y pesos son arbitrarios.
context = {
"project": "App RAG para documentación interna",
"stage": "MVP",
"team": "1 developer full-time",
"budget": "$0-50/mes",
"timeline": "Online en 1 semana",
"users": "~50 internos",
"traffic_pattern": "Horario laboral, 9am-6pm",
"ai_features": ["chat", "search", "document Q&A"],
"constraints": ["streaming para chat", "no compliance especial"],
}
Paso 2: Selecciona criterios relevantes
No uses los mismos criterios para todos los proyectos. Selecciona los que importan para TU caso:
# Criterios estándar (empezar con estos)
standard_criteria = [
"Coste mensual",
"Complejidad operativa",
"Time-to-deploy",
"Escalabilidad",
"Control",
]
# Criterios AI-specific (agregar según caso)
ai_criteria = [
"Cold starts (latencia primera request)",
"Streaming support (SSE/WebSocket)",
"Memory para modelos/embeddings",
"GPU availability",
"Timeout limits",
]
# Para este caso: standard + streaming + cold starts
selected_criteria = standard_criteria + [
"Streaming support",
"Cold starts",
]
Paso 3: Asigna pesos (deben sumar 100)
Los pesos reflejan TUS prioridades, no "mejores prácticas" universales:
weights = {
"Coste mensual": 25, # Budget es constraint principal
"Complejidad operativa": 20, # Solo yo, necesito que sea simple
"Time-to-deploy": 20, # Necesito MVP rápido
"Escalabilidad": 10, # No urgente, 50 usuarios
"Control": 5, # Sin compliance
"Streaming support": 15, # Feature clave para chat
"Cold starts": 5, # Aceptable si <3s
}
assert sum(weights.values()) == 100, "Pesos deben sumar 100"
Paso 4: Evalúa cada opción (1-5)
Sé honesto y específico. "5" no significa "perfecto" — significa "la mejor opción en esta dimensión."
evaluation = {
"Coste mensual": {
"Local": 4, # VPS $24/mes, predecible
"Serverless": 5, # ~$1-5/mes a este volumen
"Managed": 5, # Free tier cubre MVP
"Self-hosted": 1, # $30 infra + $400 ops
},
"Streaming support": {
"Local": 5, # FastAPI + uvicorn nativo
"Serverless": 1, # Lambda no soporta streaming
"Managed": 4, # Railway soporta WebSockets
"Self-hosted": 5, # Control total
},
# ... demás criterios
}
Paso 5: Calcula scores ponderados
def calculate_matrix(weights: dict, evaluation: dict) -> dict:
"""Calcula scores ponderados para cada opción."""
options = ["Local", "Serverless", "Managed", "Self-hosted"]
scores = {opt: 0 for opt in options}
for criterion, weight in weights.items():
for option in options:
score = evaluation[criterion][option]
scores[option] += weight * score
return dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))
results = calculate_matrix(weights, evaluation)
# {'Managed': 415, 'Serverless': 400, 'Local': 340, 'Self-hosted': 225}
Paso 6: Documenta la decisión y condiciones de re-evaluación
La decisión no es solo "qué elegí" sino "bajo qué condiciones re-evaluaré":
decision = {
"recommendation": "Managed (Railway)",
"score": 415,
"runner_up": "Local (VPS)",
"runner_up_score": 340,
"reasoning": "Streaming support descartó Serverless a pesar de buen score. "
"Railway ofrece WebSockets + free tier + deploy en minutos.",
"re_evaluate_when": [
"Tráfico supere 10K req/día",
"Necesite GPU para modelos locales",
"Budget cambie a >$100/mes",
"Railway cambie pricing o descontinúe features",
],
"review_date": "3 meses desde deploy",
}
Patrones Comunes de Decision Matrix
Patrón 1: MVP con presupuesto cero
Peso dominante: Coste (40) + Time-to-deploy (30)
Resultado típico: Managed (free tier) gana
Excepción: Si necesitas streaming y la plataforma no lo soporta → Local
Patrón 2: Startup en crecimiento
Peso dominante: Escalabilidad (30) + Coste (25)
Resultado típico: Serverless o Managed con auto-scale
Excepción: Si workload es constante (no picos) → Local (VPS, coste fijo)
Patrón 3: Enterprise con compliance
Peso dominante: Control (35) + Seguridad (25, criterio extra)
Resultado típico: Self-hosted o Local en VPC privada
Excepción: Raramente — compliance suele requerir control
Patrón 4: AI con modelos locales
Peso dominante: Memory/GPU (30) + Control (25)
Resultado típico: Self-hosted (GPU instances)
Excepción: Si modelo es pequeño (<4GB) → Local en VPS con RAM suficiente
Ejemplo Completo: Decision Matrix de Principio a Fin
Vamos a construir una decision matrix completa para un caso concreto. Sigue cada paso y al final tendrás un resultado numérico con recomendación.
El caso: NotifyAI
NotifyAI es un servicio que analiza mentions de tu marca en redes sociales y envía un resumen diario por email usando un LLM.
context = {
"project": "NotifyAI — Social media AI monitor",
"stage": "MVP",
"team": "1 developer (tú)",
"budget": "$0-25/mes",
"users": "Solo tú + 3 clientes beta",
"traffic": "~200 requests/día (análisis de mentions)",
"ai_features": ["Sentiment analysis", "Summary generation"],
"constraints": ["Sin streaming", "Latencia no crítica (batch process)"],
}
Paso a paso con NotifyAI
# Paso 1: Criterios y pesos (suman 100)
criteria = {
"Coste mensual": 35, # Budget es la constraint #1
"Complejidad operativa": 25, # Solo yo, necesito algo simple
"Time-to-deploy": 25, # Quiero lanzar esta semana
"Escalabilidad": 5, # 200 req/día, no necesito escala
"Control": 10, # Sin compliance, pero quiero debug fácil
}
# Paso 2: Evaluación (1-5) con justificación
evaluation = {
"Coste mensual": {"Local": 4, "Serverless": 5, "Managed": 5, "Self-hosted": 1},
"Complejidad operativa": {"Local": 3, "Serverless": 4, "Managed": 5, "Self-hosted": 1},
"Time-to-deploy": {"Local": 3, "Serverless": 3, "Managed": 5, "Self-hosted": 1},
"Escalabilidad": {"Local": 2, "Serverless": 5, "Managed": 3, "Self-hosted": 4},
"Control": {"Local": 4, "Serverless": 2, "Managed": 3, "Self-hosted": 5},
}
# Paso 3: Cálculo
options = ["Local", "Serverless", "Managed", "Self-hosted"]
totals = {opt: 0 for opt in options}
print(f"{'Criterio':<25} {'Peso':>4} | {'Local':>6} {'Server':>7} {'Managed':>8} {'Self':>6}")
print("-" * 70)
for criterion, weight in criteria.items():
scores = evaluation[criterion]
row = f"{criterion:<25} {weight:>4} |"
for opt in options:
weighted = weight * scores[opt]
totals[opt] += weighted
row += f" {weighted:>6}"
print(row)
print("-" * 70)
row = f"{'TOTAL':<25} {'':>4} |"
for opt in options:
row += f" {totals[opt]:>6}"
print(row)
Output:
Criterio Peso | Local Server Managed Self
----------------------------------------------------------------------
Coste mensual 35 | 140 175 175 35
Complejidad operativa 25 | 75 100 125 25
Time-to-deploy 25 | 75 75 125 25
Escalabilidad 5 | 10 25 15 20
Control 10 | 40 20 30 50
----------------------------------------------------------------------
TOTAL | 340 395 470 155
Decisión: Managed (470) gana por margen claro. Para un MVP de 200 req/día con 1 developer y budget mínimo, Railway con free tier es la opción óptima. Serverless (395) es alternativa viable. Self-hosted (155) está fuera de discusión.
Script reutilizable: decision_matrix.py
# decision_matrix.py — Copia, modifica los datos, ejecuta
def run_decision_matrix(criteria: dict, evaluation: dict):
"""Ejecuta una decision matrix completa y muestra resultados."""
options = list(list(evaluation.values())[0].keys())
assert sum(criteria.values()) == 100, f"Pesos suman {sum(criteria.values())}, deben sumar 100"
totals = {opt: 0 for opt in options}
for criterion, weight in criteria.items():
for opt in options:
totals[opt] += weight * evaluation[criterion][opt]
max_possible = sum(criteria.values()) * 5
sorted_results = sorted(totals.items(), key=lambda x: x[1], reverse=True)
print(f"\n{'='*50}")
print(f" DECISION MATRIX RESULTS")
print(f"{'='*50}")
for rank, (opt, score) in enumerate(sorted_results, 1):
pct = score / max_possible * 100
bar = "#" * int(pct / 5)
marker = " ← RECOMENDADO" if rank == 1 else ""
print(f" {rank}. {opt:<15} {score:>4}/{max_possible} ({pct:.0f}%) {bar}{marker}")
print(f"{'='*50}\n")
winner, w_score = sorted_results[0]
runner, r_score = sorted_results[1]
gap = (w_score - r_score) / max_possible * 100
if gap < 5:
print(f" ⚠️ Resultado reñido ({gap:.1f}% diferencia). Considera factores cualitativos.")
else:
print(f" ✅ Resultado claro ({gap:.1f}% diferencia). {winner} es la recomendación.")
return sorted_results
# === USA TUS DATOS AQUÍ ===
my_criteria = {
"Coste mensual": 30,
"Complejidad": 25,
"Time-to-deploy": 20,
"Escalabilidad": 15,
"Control": 10,
}
my_evaluation = {
"Coste mensual": {"Local": 4, "Serverless": 5, "Managed": 4, "Self-hosted": 1},
"Complejidad": {"Local": 3, "Serverless": 4, "Managed": 5, "Self-hosted": 1},
"Time-to-deploy": {"Local": 3, "Serverless": 4, "Managed": 5, "Self-hosted": 1},
"Escalabilidad": {"Local": 2, "Serverless": 5, "Managed": 3, "Self-hosted": 4},
"Control": {"Local": 4, "Serverless": 2, "Managed": 3, "Self-hosted": 5},
}
run_decision_matrix(my_criteria, my_evaluation)
Cuándo Re-evaluar Tu Decision Matrix
Triggers de re-evaluación
Una decision matrix no es un documento estático. Hay señales claras de que necesitas volver a evaluarla:
| Trigger | Ejemplo | Acción |
|---|---|---|
| Cambio de stage | Pasas de MVP a Growth (>1K usuarios) | Re-evalúa escalabilidad y coste |
| Cambio de presupuesto | Tu empresa aprueba $500/mes para infra | Re-evalúa opciones antes descartadas por coste |
| Nuevo requerimiento técnico | Necesitas streaming que antes no tenías | Re-evalúa: Lambda queda descartado |
| Cambio en el equipo | Contratas un DevOps | Self-hosted se vuelve viable |
| Cambio de pricing del proveedor | Railway sube precios o elimina free tier | Re-evalúa alternativas |
| Incidentes repetidos | 3+ caídas en un mes con tu estrategia actual | Evalúa migración |
Frecuencia recomendada
- Revisión programada: Cada 3 meses
- Revisión por trigger: Inmediatamente cuando ocurre un trigger
- Revisión light: Mensualmente, verifica que los costes reales coinciden con las estimaciones
Qué documentar en cada re-evaluación
## Re-evaluación: [Fecha]
- Trigger: [Qué motivó la revisión]
- Datos actuales: [Tráfico real, costes reales, incidentes]
- ¿Cambió el ranking? [Sí/No]
- Acción: [Mantener / Migrar a X / Investigar X]
Errores Comunes en Decision Matrices
Error 1: Pesos uniformes
❌ Todos los criterios pesan 20 (5 × 20 = 100)
→ Todas las dimensiones "importan igual"
→ Resultado: Siempre gana la opción más "balanceada" (managed)
→ Problema: No refleja TUS prioridades
✅ Pesos diferenciados según TU caso
→ Si el coste es tu constraint, dale 30-40
→ Si el control es irrelevante, dale 5
→ El resultado refleja TU realidad
Error 2: Evaluar opciones sin datos
❌ "Serverless: Escalabilidad = 5" (porque "Lambda escala")
→ Sin verificar si escala bien para TU workload
✅ "Serverless: Escalabilidad = 4"
→ Lambda escala automáticamente, pero cold starts de 8s
con mis dependencias reducen la utilidad del auto-scale
para requests interactivos
Error 3: No documentar condiciones de re-evaluación
❌ Decisión: "Usamos Railway"
→ ¿Cuándo dejamos de usarlo? ¿Si crecemos? ¿Si cambian precios?
✅ Decisión: "Usamos Railway"
Re-evaluar cuando:
- Tráfico > 500 req/hora (verificar limits)
- Budget > $100/mes (considerar VPS)
- Necesitemos servicios AWS (S3, SageMaker)
Review: Q2 2026
Troubleshooting
Problema 1: "Mis pesos se sienten arbitrarios"
Solución: Usa la técnica de comparación por pares. Para cada par de criterios, pregúntate: "¿Prefiero optimizar A o B?" El criterio que gana más comparaciones recibe más peso. Para 5 criterios, hay 10 comparaciones — en 5 minutos tienes pesos más robustos que "a ojo."
Problema 2: "El ganador tiene un deal-breaker funcional"
Solución: Los deal-breakers no se capturan en scores numéricos. Antes de calcular, identifica deal-breakers: si necesitas streaming, Lambda tiene score 0 (no 1-5) en esa dimensión. Elimina opciones con deal-breakers antes de la evaluación numérica.
Problema 3: "Mi matrix da un empate técnico"
Solución: Un empate (<5% diferencia) significa que ambas opciones son viables para tu caso. Elige por: (1) familiaridad del equipo, (2) facilidad de migración futura, o (3) la que tenga mejor documentación. Documenta que fue empate y por qué elegiste la que elegiste.
Problema 4: "No tengo datos reales para evaluar"
Solución: Usa estimaciones conservadoras (peor caso razonable) y marca las evaluaciones como "estimadas." Después de 2-4 semanas en producción, actualiza con datos reales. La primera matrix es una hipótesis informada — no necesita ser perfecta para ser útil.
Ejercicios Prácticos
Ejercicio 1: Construye tu matrix desde cero
Usa el template de esta cápsula para construir una decision matrix para tu app AI. Incluye contexto, criterios con pesos, evaluación 1-5, y score ponderado.
Ver solución
No hay solución fija — depende de tu caso. Verifica que:
- Los pesos suman 100
- Cada evaluación tiene justificación (no solo números)
- Hay condiciones de re-evaluación documentadas
- La decisión incluye segunda opción y descartados con razón
Si tu matrix produce un ganador claro (>20% sobre la segunda opción), tu caso tiene constraints fuertes. Si está reñido (<10% diferencia), cualquiera de los top-2 es viable — elige por experiencia o preferencia.
Ejercicio 2: Sensitivity analysis
Toma tu matrix del Ejercicio 1. Cambia el peso del criterio #1 de su valor actual a 10 menos. ¿Cambia el ganador?
Ver solución
Si al cambiar un peso ±10 puntos el ganador cambia, tu decisión es sensible a ese criterio. Eso significa:
- Necesitas ser muy preciso en la evaluación de ese criterio
- Un cambio en tus circunstancias (ej: más presupuesto) puede cambiar la recomendación
- Documenta esto en las condiciones de re-evaluación
Si el ganador no cambia, tu decisión es robusta — la opción gana bajo múltiples combinaciones de pesos.
Ejercicio 3: Matrix para un caso diferente al tuyo
Construye una matrix para un caso opuesto al tuyo: si tu caso es MVP con 1 developer, haz una matrix para enterprise con equipo de 10. ¿Cambian los criterios? ¿Los pesos?
Ver solución
En un caso enterprise con equipo de 10:
- Control pesa más (compliance, auditoría)
- Coste pesa menos (presupuesto mayor)
- Escalabilidad pesa más (más usuarios)
- Time-to-deploy pesa menos (proceso más formal)
- Criterios nuevos: SLA, multi-region, disaster recovery
El resultado probablemente favorece Self-hosted o AWS managed services en lugar de Railway/Render. Este ejercicio demuestra que la matrix es un framework, no una respuesta fija.
Ejercicio 4: Pitch la decisión
Prepara una presentación de 2 minutos de tu decision matrix para un stakeholder no-técnico. Incluye: el contexto, los 3 criterios más importantes, el ganador, y cuándo re-evaluar.
Ver solución
Ejemplo:
"Necesitamos deployar nuestra app AI de documentación. Evalué 4 opciones de infraestructura usando 7 criterios ponderados por nuestras prioridades: presupuesto limitado, equipo de una persona, y necesidad de streaming para el chat.
Railway ganó con 415 puntos de 500 posibles. Las dos razones principales: (1) free tier cubre nuestro volumen actual, y (2) soporta WebSockets que necesitamos para streaming. La alternativa es un servidor propio con Docker, que nos da más control pero cuesta más en mi tiempo.
Re-evaluamos en 3 meses o si superamos 500 requests/hora. Tengo la matrix documentada para cuando lo necesitemos."
Clave: Simplifica para no-técnicos. "4 opciones, 7 criterios, Railway gana por coste y features."
Resumen
- Una decision matrix convierte análisis de trade-offs en una decisión documentada y defendible.
- Los 6 pasos son: contexto → criterios → pesos → evaluación → scores → decisión + re-evaluación.
- Los pesos deben reflejar TUS prioridades, no best practices genéricas. Que sumen 100.
- La evaluación (1-5) debe tener justificación, no solo números.
- Los errores más comunes son: pesos uniformes, evaluación sin datos, y no documentar condiciones de re-evaluación.
- Una buena matrix incluye sensitivity analysis: ¿cambia el resultado si cambio un peso?
- La matrix se reutiliza: Módulo 7 (plataformas), Módulo 8 (proyecto integrador).
Recursos Adicionales
- Decision Matrix Analysis — MindTools — Framework general de decision matrices
- Pugh Matrix — Método formal de decisión ponderada
- Architecture Decision Records (ADR) — Formato para documentar decisiones de arquitectura
- DACI Framework — Framework para decisiones en equipo
- AWS Well-Architected Tool — Herramienta de evaluación de arquitectura
- Technology Radar — ThoughtWorks — Referencia para evaluar tecnologías