Módulo 7: Alternative Platforms (Render, Railway, Fly.io)
7. Decision Matrix de Plataformas: El Framework Completo
Descripción
En esta cápsula vas a extender la decision matrix del Módulo 1 con criterios de plataforma. En M1 evaluaste categorías (Local, Serverless, Managed, Self-hosted). Aquí evalúas plataformas concretas dentro de la categoría "Managed": AWS vs Render vs Railway vs Fly.io. El resultado es la decision matrix v2 — un framework completo que mapea requirements de tu proyecto a la plataforma óptima, con datos reales de las cápsulas anteriores.
Contexto: Has desplegado en Render, Railway y Fly.io. Has comparado features, pricing, limitaciones (cápsula 05). Has integrado CI/CD (cápsula 06). Ahora tienes experiencia de primera mano con cada plataforma. La decision matrix v2 formaliza esa experiencia en un framework reutilizable. Cada vez que empieces un proyecto nuevo, esta matrix te dice dónde deployar.
De Categorías a Plataformas
Recap: Decision Matrix v1 (Módulo 1)
En M1 tu matrix evaluaba categorías:
Matrix v1 (M1):
Criterios × [Local, Serverless, Managed, Self-hosted]
→ Resultado: "Para mi caso, Managed es la categoría óptima"
Eso te dice la dirección, pero no la plataforma. "Managed" incluye Render, Railway, Fly.io, Heroku, DigitalOcean App Platform, Google Cloud Run, Azure Container Apps... Necesitas un segundo nivel de decisión.
Decision Matrix v2: Plataformas
Matrix v2 (M7):
Criterios × [AWS, Render, Railway, Fly.io]
→ Resultado: "Para mi caso, Railway es la plataforma óptima"
Framework completo:
Matrix v1 → Categoría → Matrix v2 → Plataforma → Deploy
La v2 no reemplaza la v1 — la extiende. Si tu v1 dice "Serverless," tu plataforma es AWS Lambda (la única opción en esta guía). Si dice "Managed," la v2 elige entre Render, Railway y Fly.io. Si dice "Local," no necesitas plataforma cloud. La v2 solo aplica cuando la categoría óptima es Managed o cuando quieres comparar Managed vs AWS.
Criterios de Plataforma para AI
Criterios estándar (de M1, adaptados)
| # | Criterio | Descripción | Relevancia AI |
|---|---|---|---|
| 1 | Coste mensual | Infra + APIs + ops | Alta — APIs LLM dominan, pero infra importa |
| 2 | Developer experience | Setup, CLI, workflows, logs | Alta — iteración rápida = mejor producto |
| 3 | Time-to-deploy | De commit a producción | Media — importa más en MVP que en scale |
| 4 | Escalabilidad | Capacidad de crecer sin migrar | Media — depende del stage |
| 5 | Control | Acceso a configuración, debugging | Baja para managed, alta para enterprise |
Criterios AI-specific (nuevos en v2)
| # | Criterio | Descripción | Por qué es específico de AI |
|---|---|---|---|
| 6 | Request timeout | Tiempo máximo para una request HTTP | Inferencia AI puede tardar 5-30s |
| 7 | RAM disponible | Memoria máxima del servicio | Embeddings, vectores, modelos en memoria |
| 8 | WebSocket/streaming | Soporte para streaming de tokens | Chat UX requiere streaming |
| 9 | Cold start | Tiempo de arranque después de inactividad | Afecta UX en apps con tráfico irregular |
| 10 | Multi-region | Deploy en múltiples ubicaciones | Latencia global para apps con usuarios distribuidos |
Criterios de equipo/negocio
| # | Criterio | Descripción | Cuándo importa |
|---|---|---|---|
| 11 | Vendor lock-in | Dificultad de migrar a otra plataforma | Siempre — pero más en scale |
| 12 | Preview environments | Deploys temporales por PR | Equipos de 3+ developers |
| 13 | Databases integradas | PostgreSQL, Redis como add-ons | Cuando tu app necesita persistence |
| 14 | CI/CD integration | Facilidad de conectar con GitHub Actions | Equipos con CI/CD existente |
| 15 | Compliance/SLA | Garantías de uptime, certificaciones | Enterprise, datos regulados |
No necesitas todos los criterios. Selecciona 7-10 que sean relevantes para tu caso.
Evaluación de Plataformas: Datos Reales
Evaluación cuantitativa (1-5)
# Evaluación basada en datos reales de las cápsulas 02-06
platform_scores = {
"AWS (Lambda + S3)": {
"Coste mensual": (3, "Pay-per-use, pero setup + monitoring tiene coste oculto"),
"Developer experience": (2, "IAM, API Gateway, CloudWatch — curva de aprendizaje alta"),
"Time-to-deploy": (1, "30-60 min primera vez, 5-10 min redeploy"),
"Escalabilidad": (5, "Auto-scaling nativo, prácticamente ilimitado"),
"Control": (5, "Configuración granular de todo"),
"Request timeout": (5, "Lambda: 15 min máximo"),
"RAM disponible": (4, "Lambda: hasta 10 GB. EC2: ilimitado"),
"WebSocket/streaming": (3, "API Gateway WebSocket existe pero es complejo"),
"Cold start": (2, "Lambda cold start: 1-10s, peor con container images"),
"Multi-region": (5, "Nativo con configuración"),
"Vendor lock-in": (1, "Alto — IAM, API Gateway, CloudWatch, Lambda specifics"),
"Preview environments": (2, "Manual — stages en API Gateway o stacks separados"),
"Databases integradas": (4, "RDS, ElastiCache, DynamoDB — todo managed"),
"CI/CD integration": (4, "CodePipeline nativo, GitHub Actions con AWS CLI"),
"Compliance/SLA": (5, "SOC2, HIPAA, ISO, SLA 99.99%"),
},
"Render": {
"Coste mensual": (4, "Predecible: $7-85/mes por servicio"),
"Developer experience": (3, "Dashboard simple, pero sin CLI"),
"Time-to-deploy": (4, "3-5 min primera vez, auto-deploy en push"),
"Escalabilidad": (3, "Horizontal scaling, pero single region"),
"Control": (2, "Limitado — planes fijos, pocas opciones de tuning"),
"Request timeout": (2, "30 segundos — limitante para AI"),
"RAM disponible": (3, "512 MB - 8 GB según plan"),
"WebSocket/streaming": (3, "SSE sí, WebSocket solo en Starter+"),
"Cold start": (2, "Free: 15-45s. Starter+: 0"),
"Multi-region": (1, "4 regiones, pero single region por servicio"),
"Vendor lock-in": (4, "Bajo — Docker container + render.yaml simple"),
"Preview environments": (2, "En beta, no maduro"),
"Databases integradas": (3, "PostgreSQL y Redis managed"),
"CI/CD integration": (3, "Auto-deploy nativo, API para GitHub Actions"),
"Compliance/SLA": (2, "Básico — no SOC2, SLA limitado"),
},
"Railway": {
"Coste mensual": (3, "Pay-per-use: ~$25-30/mes para app AI típica"),
"Developer experience": (5, "CLI excelente, preview envs, add-ons con un click"),
"Time-to-deploy": (5, "2-3 min con CLI, el más rápido"),
"Escalabilidad": (3, "Auto-scaling en Pro, pero single region"),
"Control": (3, "Más que Render, menos que AWS"),
"Request timeout": (4, "5 minutos — suficiente para mayoría de AI"),
"RAM disponible": (4, "Hasta 32 GB en Pro"),
"WebSocket/streaming": (4, "Full WebSocket support"),
"Cold start": (3, "2-8s con sleep habilitado"),
"Multi-region": (1, "Single region"),
"Vendor lock-in": (4, "Bajo — Docker + railway.toml mínimo"),
"Preview environments": (5, "Nativo, automático, con DB aislada por PR"),
"Databases integradas": (5, "PostgreSQL, Redis, MySQL, MongoDB con un click"),
"CI/CD integration": (4, "Auto-deploy + CLI en GitHub Actions"),
"Compliance/SLA": (2, "Básico — Pro tiene SLA pero limitado"),
},
"Fly.io": {
"Coste mensual": (5, "El más barato: ~$10-15/mes para app AI"),
"Developer experience": (3, "CLI potente pero más setup inicial"),
"Time-to-deploy": (3, "5-7 min primera vez, 2-3 min redeploy"),
"Escalabilidad": (5, "Multi-region nativo, auto-start/stop"),
"Control": (4, "SSH a VMs, Machines API, configuración granular"),
"Request timeout": (4, "Configurable — sin límite hard"),
"RAM disponible": (3, "256 MB - 16 GB+"),
"WebSocket/streaming": (5, "Full support, nativo"),
"Cold start": (4, "Firecracker: 300ms-2s"),
"Multi-region": (5, "30+ regiones, anycast routing"),
"Vendor lock-in": (3, "Medio — fly.toml, volumes, multi-region config"),
"Preview environments": (2, "Manual con Machines API"),
"Databases integradas": (3, "Fly Postgres + Upstash Redis"),
"CI/CD integration": (4, "Action oficial + flyctl en CI"),
"Compliance/SLA": (3, "Mejor que Render/Railway, pero no enterprise"),
},
}
Construir Tu Decision Matrix v2
Paso 1: Seleccionar criterios relevantes
No todos los criterios aplican a tu caso. Selecciona 7-10:
def select_criteria(project_profile: dict) -> dict:
"""Selecciona criterios y pesos basados en el perfil del proyecto."""
base_criteria = {
"Coste mensual": 15,
"Developer experience": 10,
"Time-to-deploy": 10,
"Request timeout": 10,
"RAM disponible": 10,
}
if project_profile.get("streaming"):
base_criteria["WebSocket/streaming"] = 15
if project_profile.get("global_users"):
base_criteria["Multi-region"] = 15
if project_profile.get("team_size", 1) > 2:
base_criteria["Preview environments"] = 10
if project_profile.get("needs_database"):
base_criteria["Databases integradas"] = 10
if project_profile.get("enterprise"):
base_criteria["Compliance/SLA"] = 15
if project_profile.get("irregular_traffic"):
base_criteria["Cold start"] = 10
total = sum(base_criteria.values())
normalized = {k: round(v / total * 100) for k, v in base_criteria.items()}
remainder = 100 - sum(normalized.values())
first_key = list(normalized.keys())[0]
normalized[first_key] += remainder
return normalized
Paso 2: Asignar pesos
Los pesos reflejan TUS prioridades, no "la verdad universal":
# Ejemplo: MVP de chatbot AI, 1 developer, presupuesto limitado
mvp_criteria = {
"Coste mensual": 25,
"Developer experience": 20,
"Time-to-deploy": 15,
"Request timeout": 15,
"WebSocket/streaming": 15,
"Cold start": 10,
}
# Ejemplo: App AI para empresa, equipo de 5, usuarios globales
enterprise_criteria = {
"Escalabilidad": 20,
"Multi-region": 15,
"Compliance/SLA": 15,
"RAM disponible": 10,
"Databases integradas": 10,
"Preview environments": 10,
"CI/CD integration": 10,
"Coste mensual": 10,
}
assert sum(mvp_criteria.values()) == 100
assert sum(enterprise_criteria.values()) == 100
Paso 3: Calcular scores ponderados
def calculate_platform_scores(
criteria: dict, evaluations: dict
) -> dict:
"""Calcula scores ponderados para cada plataforma."""
platforms = list(evaluations.keys())
results = {}
for platform in platforms:
total = 0
details = {}
for criterion, weight in criteria.items():
if criterion in evaluations[platform]:
score, note = evaluations[platform][criterion]
weighted = weight * score
total += weighted
details[criterion] = {
"score": score,
"weight": weight,
"weighted": weighted,
"note": note,
}
results[platform] = {"total": total, "details": details}
max_possible = sum(criteria.values()) * 5
sorted_results = dict(
sorted(results.items(), key=lambda x: x[1]["total"], reverse=True)
)
return {"rankings": sorted_results, "max_possible": max_possible}
# Ejemplo con criterios de MVP
mvp_results = calculate_platform_scores(mvp_criteria, platform_scores)
print("=== Rankings para MVP AI Chatbot ===\n")
print(f"{'Platform':<25} {'Score':>6} {'%':>6}")
print("-" * 40)
for platform, data in mvp_results["rankings"].items():
pct = data["total"] / mvp_results["max_possible"] * 100
print(f"{platform:<25} {data['total']:>6} {pct:>5.1f}%")
Paso 4: Interpretar resultados
def interpret_results(results: dict) -> str:
"""Genera interpretación automática de los resultados."""
rankings = list(results["rankings"].items())
winner = rankings[0]
runner_up = rankings[1]
max_score = results["max_possible"]
diff = winner[1]["total"] - runner_up[1]["total"]
diff_pct = diff / max_score * 100
interpretation = f"""
## Resultado
**Plataforma recomendada: {winner[0]}**
- Score: {winner[1]['total']}/{max_score} ({winner[1]['total']/max_score*100:.0f}%)
**Segunda opción: {runner_up[0]}**
- Score: {runner_up[1]['total']}/{max_score} ({runner_up[1]['total']/max_score*100:.0f}%)
**Diferencia: {diff_pct:.1f}%**
"""
if diff_pct < 5:
interpretation += """
⚠️ **Diferencia marginal (<5%).** Ambas plataformas son viables.
Considera factores cualitativos: familiaridad del equipo, preferencia de CLI vs dashboard.
"""
elif diff_pct < 15:
interpretation += """
La diferencia es moderada. La recomendación es clara pero la segunda
opción es viable si hay constraints no capturados en la matrix.
"""
else:
interpretation += """
La diferencia es significativa. La plataforma recomendada es claramente
superior para este caso de uso.
"""
return interpretation
Escenarios Predefinidos
Escenario 1: MVP / Proyecto Personal
mvp_profile = {
"team_size": 1,
"budget": "$0-20/mes",
"users": "<100",
"traffic": "irregular",
"streaming": False,
"global_users": False,
"enterprise": False,
}
mvp_weights = {
"Coste mensual": 30,
"Time-to-deploy": 25,
"Developer experience": 20,
"Cold start": 15,
"RAM disponible": 10,
}
# Resultado típico: Fly.io o Railway
# Fly.io gana en coste (free tier más generoso)
# Railway gana en DX (más rápido de setup)
Escenario 2: Startup Early-Stage
startup_profile = {
"team_size": 3,
"budget": "$50-100/mes",
"users": "500-5000",
"traffic": "growing",
"streaming": True,
"global_users": False,
"enterprise": False,
"needs_database": True,
}
startup_weights = {
"Developer experience": 20,
"Databases integradas": 15,
"WebSocket/streaming": 15,
"Preview environments": 15,
"Coste mensual": 15,
"Request timeout": 10,
"CI/CD integration": 10,
}
# Resultado típico: Railway
# Preview environments + add-ons + DX
Escenario 3: App AI con Usuarios Globales
global_profile = {
"team_size": 5,
"budget": "$200-500/mes",
"users": "10000+",
"traffic": "high, global",
"streaming": True,
"global_users": True,
"enterprise": False,
}
global_weights = {
"Multi-region": 25,
"Escalabilidad": 20,
"WebSocket/streaming": 15,
"Request timeout": 10,
"RAM disponible": 10,
"CI/CD integration": 10,
"Coste mensual": 10,
}
# Resultado típico: Fly.io o AWS
# Fly.io gana en multi-region + simplicidad
# AWS gana si necesitas SageMaker o compliance
Escenario 4: Enterprise / Compliance
enterprise_profile = {
"team_size": 10,
"budget": "$500+/mes",
"users": "enterprise",
"enterprise": True,
"needs_database": True,
}
enterprise_weights = {
"Compliance/SLA": 25,
"Escalabilidad": 20,
"Control": 15,
"Databases integradas": 10,
"Multi-region": 10,
"CI/CD integration": 10,
"RAM disponible": 10,
}
# Resultado típico: AWS
# Ninguna plataforma alternativa tiene SOC2/HIPAA/enterprise SLA
El Framework Completo: Cuándo Usar Cada Plataforma
Decision Tree
¿Necesitas compliance enterprise (SOC2, HIPAA, ISO)?
├── Sí → AWS
└── No ↓
¿Necesitas GPU para inferencia local?
├── Sí → Servicios especializados (RunPod, Lambda Labs)
└── No ↓
¿Tu categoría óptima (M1) es Serverless?
├── Sí → AWS Lambda
└── No (Managed) ↓
¿Necesitas multi-region o edge deployment?
├── Sí → Fly.io
└── No ↓
¿Equipos de 3+ developers con PRs frecuentes?
├── Sí → Railway (preview environments)
└── No ↓
¿Prioridad: pricing predecible?
├── Sí → Render
└── No ↓
¿Prioridad: velocidad de iteración?
├── Sí → Railway
└── No ↓
¿Prioridad: coste mínimo?
└── Fly.io
Resumen ejecutivo
| Plataforma | Elige cuando | Evita cuando |
|---|---|---|
| AWS | Compliance, scale enterprise, servicios específicos (SageMaker, Lambda@Edge) | MVP, equipo pequeño, presupuesto <$50/mes |
| Render | Simplicidad máxima, pricing predecible, demos | Necesitas streaming largo (timeout 30s), multi-region |
| Railway | Mejor DX, equipos con PRs, prototipos rápidos | Presupuesto muy limitado ($0), necesitas multi-region |
| Fly.io | Multi-region, coste mínimo, WebSocket nativo | Quieres dashboard-first workflow, equipo no técnico |
Sensitivity Analysis
¿Qué pasa si cambias los pesos?
Un buen framework de decisión sobrevive a variaciones en los pesos. Si cambiar un peso ±10 cambia la recomendación, la diferencia entre plataformas es marginal y deberías elegir por factores cualitativos.
def sensitivity_analysis(
base_criteria: dict,
evaluations: dict,
vary_criterion: str,
vary_range: range = range(-10, 15, 5),
) -> list:
"""Analiza cómo cambia el ganador al variar el peso de un criterio."""
results = []
for delta in vary_range:
adjusted = base_criteria.copy()
original = adjusted[vary_criterion]
adjusted[vary_criterion] = max(0, original + delta)
total = sum(adjusted.values())
if total == 0:
continue
normalized = {k: round(v / total * 100) for k, v in adjusted.items()}
scores = calculate_platform_scores(normalized, evaluations)
winner = list(scores["rankings"].keys())[0]
winner_score = list(scores["rankings"].values())[0]["total"]
results.append({
"delta": delta,
"weight": max(0, original + delta),
"winner": winner,
"score": winner_score,
})
return results
# Ejemplo: ¿Qué pasa si el coste importa más/menos?
analysis = sensitivity_analysis(mvp_criteria, platform_scores, "Coste mensual")
for r in analysis:
print(f" Coste peso={r['weight']:>3}: Ganador = {r['winner']:<20} (score: {r['score']})")
Interpretación de sensitivity analysis
Si el ganador cambia con ±5 de peso:
→ La decisión es marginal. Elige por familiaridad del equipo.
Si el ganador cambia con ±10 de peso:
→ La decisión es robusta pero no aplastante. Documenta la segunda opción.
Si el ganador NO cambia con ±15 de peso:
→ La decisión es sólida. La plataforma recomendada es claramente superior.
Ejercicios Prácticos
Ejercicio 1: Construir tu decision matrix v2
Toma los criterios de esta cápsula, selecciona 7-10 relevantes para tu caso, asigna pesos, y calcula scores. Produce un ranking documentado.
Ver solución
# decision_matrix_v2.py
# 1. Define tu perfil
my_profile = {
"project": "DocuSearch AI",
"stage": "MVP → Growth",
"team": 2,
"budget": "$30-50/mes",
"users_current": 150,
"users_target": 500,
"needs_streaming": True,
"needs_database": True,
"global_users": False,
}
# 2. Selecciona criterios y pesos (suman 100)
my_criteria = {
"Coste mensual": 20,
"Developer experience": 15,
"Request timeout": 15,
"WebSocket/streaming": 15,
"Databases integradas": 10,
"RAM disponible": 10,
"Cold start": 10,
"CI/CD integration": 5,
}
assert sum(my_criteria.values()) == 100
# 3. Evalúa (usa los datos de platform_scores arriba)
# ... (ejecuta calculate_platform_scores)
# 4. Genera el documento
print(f"""
# Decision Matrix v2: {my_profile['project']}
Fecha: 2026-03-08
Stage: {my_profile['stage']}
Team: {my_profile['team']} developers
## Criterios y Pesos
""")
for criterion, weight in sorted(my_criteria.items(), key=lambda x: -x[1]):
print(f"| {criterion} | {weight} |")
# 5. Calcula y muestra resultados
results = calculate_platform_scores(my_criteria, platform_scores)
print("\n## Rankings")
for platform, data in results["rankings"].items():
pct = data["total"] / results["max_possible"] * 100
print(f"| {platform} | {data['total']} | {pct:.0f}% |")
Ejercicio 2: Sensitivity analysis de tu matrix
Ejecuta sensitivity analysis variando los 3 criterios con mayor peso. Determina si tu recomendación es robusta.
Ver solución
# sensitivity.py
top_3_criteria = sorted(my_criteria.items(), key=lambda x: -x[1])[:3]
print("=== Sensitivity Analysis ===\n")
for criterion, weight in top_3_criteria:
print(f"\n--- Variando: {criterion} (base: {weight}) ---")
analysis = sensitivity_analysis(
my_criteria, platform_scores, criterion, range(-15, 20, 5)
)
changes = set()
for r in analysis:
changes.add(r["winner"])
print(f" peso={r['weight']:>3}: {r['winner']:<20} (score: {r['score']})")
if len(changes) == 1:
print(f" → Resultado ESTABLE: siempre {list(changes)[0]}")
else:
print(f" → Resultado SENSIBLE: cambia entre {', '.join(changes)}")
print("\n## Conclusión")
# Si los 3 criterios principales producen resultado estable:
# → Tu recomendación es sólida
# Si 1+ produce resultado sensible:
# → Documenta las condiciones bajo las cuales la recomendación cambia
Ejercicio 3: Comparar escenarios MVP vs Scale
Calcula la matrix para tu app en stage MVP Y en stage Scale. Documenta cómo cambia la recomendación cuando creces.
Ver solución
mvp_criteria = {
"Coste mensual": 25,
"Developer experience": 20,
"Time-to-deploy": 20,
"Request timeout": 15,
"Cold start": 10,
"WebSocket/streaming": 10,
}
scale_criteria = {
"Escalabilidad": 25,
"Multi-region": 15,
"Compliance/SLA": 15,
"RAM disponible": 10,
"Databases integradas": 10,
"CI/CD integration": 10,
"Preview environments": 10,
"Coste mensual": 5,
}
assert sum(mvp_criteria.values()) == 100
assert sum(scale_criteria.values()) == 100
mvp_results = calculate_platform_scores(mvp_criteria, platform_scores)
scale_results = calculate_platform_scores(scale_criteria, platform_scores)
print("=== MVP Stage ===")
for p, d in mvp_results["rankings"].items():
print(f" {p}: {d['total']}")
print("\n=== Scale Stage ===")
for p, d in scale_results["rankings"].items():
print(f" {p}: {d['total']}")
mvp_winner = list(mvp_results["rankings"].keys())[0]
scale_winner = list(scale_results["rankings"].keys())[0]
if mvp_winner != scale_winner:
print(f"\n⚠️ La recomendación CAMBIA: {mvp_winner} (MVP) → {scale_winner} (Scale)")
print("Documenta el migration path en tu decision matrix.")
else:
print(f"\n✅ La recomendación es CONSISTENTE: {mvp_winner} para ambos stages")
## Resultado típico
MVP: Railway (DX + coste razonable)
Scale: AWS (compliance + escalabilidad + multi-region)
Migration path:
1. MVP → Growth: Mantener Railway, agregar Redis, optimizar queries
2. Growth → Scale: Migrar a AWS cuando compliance o multi-region sea requerido
3. Trigger: >5000 usuarios O requerimiento SOC2/HIPAA O factura >$200/mes
Ejercicio 4: Documento de decisión para tu equipo
Genera un documento de decisión completo (estilo ADR) que podrías compartir con tu equipo o incluir en la documentación del proyecto.
Ver solución
# ADR-001: Platform Selection for DocuSearch AI
## Status: Accepted
## Date: 2026-03-08
## Decision Makers: [Tu nombre]
## Context
DocuSearch AI es una API RAG que usa GPT-4o-mini para responder
preguntas sobre documentación técnica. Actualmente corre en Docker
Compose local. Necesitamos deployar a producción.
## Decision
**Plataforma elegida: Railway**
## Rationale
Decision matrix v2 con 8 criterios ponderados:
- Railway: 380/500 (76%)
- Fly.io: 355/500 (71%)
- Render: 330/500 (66%)
- AWS: 290/500 (58%)
Railway gana por:
1. Developer experience (CLI + preview environments)
2. Request timeout 5 min (suficiente para RAG + streaming)
3. Add-ons integrados (PostgreSQL + Redis con un click)
4. Coste razonable (~$25-30/mes)
## Alternatives Considered
- **Fly.io:** Más barato y multi-region, pero nuestros usuarios
están todos en Latam. Multi-region no justifica la complejidad extra.
- **Render:** Más simple, pero timeout de 30s es limitante
para queries RAG complejas.
- **AWS:** Demasiada complejidad para nuestro stage (MVP, equipo de 2).
## Consequences
- Deploy via `railway up` y auto-deploy en push a main
- CI/CD con GitHub Actions → staging → production
- PostgreSQL y Redis como add-ons de Railway
- Si crecemos >5000 usuarios o necesitamos compliance:
re-evaluar con migration path a AWS
## Re-evaluation Triggers
- [ ] >5000 usuarios activos
- [ ] Factura Railway >$100/mes
- [ ] Requerimiento SOC2/HIPAA
- [ ] Necesidad de multi-region (usuarios globales)
- [ ] Review programado: 2026-06-08 (3 meses)
Troubleshooting
Problema 1: "Dos plataformas tienen scores muy cercanos (<5%)"
Solución: Ejecuta sensitivity analysis. Si la diferencia es marginal, elige por:
- Familiaridad del equipo (ya usaste Railway en un proyecto → Railway)
- Ecosistema (ya tienes PostgreSQL en Railway → quédate)
- Haz un deploy de prueba en ambas y elige por experiencia
Problema 2: "Mi matrix dice AWS pero no quiero la complejidad"
Solución: La matrix refleja tus pesos. Si tus pesos priorizan control y compliance, AWS gana. Si eso no es tu prioridad real, ajusta los pesos. La matrix es tan honesta como tus inputs.
Problema 3: "Mi caso no encaja en ningún escenario predefinido"
Solución: Los escenarios son puntos de partida, no respuestas finales. Crea tu propio perfil, selecciona criterios relevantes, y ajusta pesos. La matrix es un framework — tú la configuras.
Resumen
- Decision matrix v2 extiende la v1 del M1 con criterios de plataforma: AWS vs Render vs Railway vs Fly.io.
- Criterios AI-specific (request timeout, RAM, streaming, cold start) son los que más diferencian plataformas para AI workloads.
- Los pesos reflejan TUS prioridades — MVP prioriza coste y DX, enterprise prioriza compliance y escalabilidad.
- Sensitivity analysis valida si tu recomendación es robusta o marginal.
- El stage del proyecto cambia la plataforma óptima: Railway para MVP → AWS para scale es un path común.
- No hay "mejor plataforma universal" — hay mejor plataforma para TU caso, TUS constraints, TU stage.
- Documenta la decisión como un ADR — tu futuro yo y tu equipo te lo agradecerán.
Recursos Adicionales
- Architecture Decision Records (ADR) — Formato estándar para documentar decisiones
- Decision Matrix — Wikipedia — Teoría de decision matrices
- Sensitivity Analysis — Investopedia — Fundamentos de sensitivity analysis
- Platform Engineering — CNCF — White paper sobre plataformas
- ThoughtWorks Technology Radar — Estado del arte en deployment platforms
- Cloud Provider Comparison — CloudOptimizer — Herramienta de comparación de providers