Simulador de Decisiones
Enfrenta escenarios reales donde debes tomar decisiones arquitectónicas y evaluar sus consecuencias a corto y largo plazo.
Objetivo
En este laboratorio vas a enfrentar una serie de escenarios donde debes tomar decisiones arquitectónicas bajo restricciones reales: tiempo, presupuesto, equipo y requisitos cambiantes. Cada decisión tiene consecuencias que se revelan en las siguientes rondas.
Cómo funciona
- Lee el escenario inicial con sus restricciones
- Elige entre las opciones disponibles (o propón la tuya)
- Lee las consecuencias de tu decisión
- Enfrenta el siguiente escenario que se deriva de tu elección anterior
No hay respuestas correctas universales — pero sí hay decisiones mejor fundamentadas que otras.
Escenario 1: El monolito que crece
Contexto
Tu empresa tiene un monolito en Node.js que lleva 3 años en producción. El equipo creció de 4 a 12 desarrolladores. Los deploys tardan 45 minutos y los conflictos de merge son constantes. El CTO quiere “migrar a microservicios”.
Restricciones
- Presupuesto: no hay para contratar más gente
- Timeline: 6 meses para mostrar resultados
- El monolito genera $2M/año en revenue — no puede caerse
Opciones
Opción A: Big bang — reescribir todo en microservicios
- Riesgo: alto (reescritura completa)
- Tiempo estimado: 8-12 meses
- Beneficio potencial: arquitectura limpia desde cero
Opción B: Strangler fig — extraer servicios gradualmente
- Riesgo: medio (cambios incrementales)
- Tiempo estimado: 3-6 meses para el primer servicio
- Beneficio potencial: valor incremental, riesgo controlado
Opción C: Monolito modular — reorganizar sin distribuir
- Riesgo: bajo (refactoring interno)
- Tiempo estimado: 2-3 meses
- Beneficio potencial: mejor organización sin complejidad distribuida
Consecuencias
Si elegiste Opción A
A los 4 meses, el equipo lleva un 30% del trabajo. El monolito sigue recibiendo features nuevas porque el negocio no puede esperar. Ahora tienes dos sistemas que mantener y el equipo está dividido. El CTO empieza a preguntar cuándo estará listo.
Lección: Las reescrituras completas casi nunca terminan a tiempo. El negocio no se detiene mientras reescribes.
Si elegiste Opción B
A los 3 meses, extrajiste el servicio de notificaciones. Los deploys del monolito son un poco más rápidos. El equipo aprendió sobre comunicación entre servicios, service discovery y monitoreo distribuido. Ahora puedes planificar la siguiente extracción con más confianza.
Lección: El patrón Strangler Fig permite migrar gradualmente con riesgo controlado. Cada extracción enseña lecciones para la siguiente.
Si elegiste Opción C
A los 2 meses, el monolito está organizado en módulos con interfaces claras. Los conflictos de merge se redujeron un 60%. Los deploys siguen tardando 45 minutos, pero ahora puedes hacer deploys parciales por módulo. El equipo tiene una base sólida para extraer servicios en el futuro si es necesario.
Lección: A veces la mejor arquitectura distribuida es la que no necesitas. Un monolito bien organizado puede escalar más de lo que crees.
Escenario 2: Elegir la base de datos
Contexto
Estás diseñando un nuevo servicio de inventario. Necesita manejar:
- 500,000 SKUs con actualizaciones frecuentes
- Consultas complejas con filtros y agregaciones
- Historial de cambios para auditoría
- Lecturas 10x más frecuentes que escrituras
Opciones
Opción A: PostgreSQL
- Modelo relacional, ACID completo
- Excelente para consultas complejas
- Escalado vertical + read replicas
Opción B: MongoDB
- Modelo de documentos, schema flexible
- Escalado horizontal nativo (sharding)
- Consultas de agregación potentes
Opción C: PostgreSQL + Redis
- PostgreSQL como fuente de verdad
- Redis como caché de lectura
- Mayor complejidad operativa
Consecuencias
Si elegiste Opción A
PostgreSQL maneja bien las 500K filas y las consultas complejas. A los 6 meses, las lecturas empiezan a saturar la base de datos. Agregas una read replica y el problema se resuelve. El historial de cambios lo implementas con una tabla de auditoría y triggers.
Lección: PostgreSQL es una elección sólida para la mayoría de los casos. No subestimes lo lejos que puede llegar una base de datos relacional bien configurada.
Si elegiste Opción B
MongoDB funciona bien al principio. A los 3 meses, descubres que las consultas de agregación con múltiples filtros son más lentas de lo esperado. El schema flexible causó inconsistencias en los datos porque diferentes partes del equipo guardaban los documentos con estructuras ligeramente diferentes.
Lección: La flexibilidad de schema es un arma de doble filo. Sin disciplina, genera deuda técnica. MongoDB brilla cuando el modelo de datos es genuinamente jerárquico.
Si elegiste Opción C
La combinación funciona muy bien para las lecturas. Pero a los 2 meses, descubres bugs de invalidación de caché: algunos usuarios ven datos stale después de actualizaciones. Implementas un sistema de invalidación basado en eventos y el problema se resuelve, pero la complejidad operativa aumentó significativamente.
Lección: Agregar caché resuelve problemas de rendimiento pero introduce problemas de consistencia. Solo agrega caché cuando realmente lo necesitas, no “por si acaso”.
Escenario 3: El servicio externo que falla
Contexto
Tu servicio de pagos depende de un proveedor externo (Stripe). En las últimas semanas, Stripe ha tenido 3 incidentes de disponibilidad que afectaron a tus usuarios. El equipo de producto quiere que “los pagos nunca fallen”.
Opciones
Opción A: Agregar un segundo proveedor (PayPal) como fallback
- Duplicas la integración de pagos
- Si Stripe falla, redirigir a PayPal automáticamente
- Mayor complejidad en reconciliación
Opción B: Implementar cola de reintentos
- Los pagos fallidos van a una cola
- Se reintentan automáticamente con backoff exponencial
- El usuario recibe notificación cuando el pago se procesa
Opción C: Circuit breaker + degradación graceful
- Detectar fallos de Stripe rápidamente
- Mostrar al usuario un mensaje claro y ofrecer reintentar más tarde
- Guardar el intento para procesarlo cuando Stripe vuelva
Consecuencias
Si elegiste Opción A
Funciona, pero la reconciliación entre dos proveedores es compleja. Algunos pagos se procesan en Stripe y otros en PayPal, lo que complica los reportes financieros. Además, PayPal tiene su propia tasa de fallos — no es inmune. A los 3 meses, tienes un sistema más resiliente pero significativamente más complejo de operar.
Lección: Múltiples proveedores aumentan la disponibilidad pero multiplican la complejidad. Evalúa si el costo operativo justifica la mejora en disponibilidad.
Si elegiste Opción B
Los reintentos automáticos resuelven el 90% de los fallos transitorios. Pero descubres un problema: algunos pagos se procesan dos veces porque el reintento llega cuando Stripe ya había procesado el primero (pero respondió con timeout). Implementas idempotencia con claves únicas y el problema se resuelve.
Lección: Los reintentos sin idempotencia son peligrosos. Siempre implementa idempotencia antes de implementar reintentos automáticos.
Si elegiste Opción C
El circuit breaker detecta los fallos en segundos y deja de enviar requests a Stripe. Los usuarios ven un mensaje claro: “El sistema de pagos está temporalmente no disponible. Tu carrito está guardado — puedes completar la compra más tarde.” La experiencia no es perfecta, pero es honesta y no genera frustración.
Lección: A veces la mejor respuesta a un fallo es ser transparente con el usuario. No todos los problemas requieren soluciones técnicas complejas.
Reflexión final
Después de completar los escenarios, reflexiona:
- ¿Tendiste a elegir la opción más compleja o la más simple?
- ¿Consideraste las restricciones (tiempo, equipo, presupuesto) o solo los requisitos técnicos?
- ¿Cambiarías alguna decisión sabiendo las consecuencias?
- ¿Qué patrón ves en tus decisiones? ¿Eres conservador o arriesgado?
Las mejores decisiones arquitectónicas no son las más sofisticadas — son las que mejor se adaptan al contexto real del proyecto.