← Volver a todos los artículos
Retos

Monolito vs. Microservicios: Qué Arquitectura Elegir para tu MVP

Por Marc Molas·22 de diciembre de 2023·10 min de lectura

Hay una conversación que tengo al menos dos veces al mes con fundadores que llegan pidiendo ayuda con su stack. Empieza así: "Queremos construir el MVP con microservicios desde el principio para no tener que reescribir después."

Es una idea que suena lógica. Y en la gran mayoría de los casos, es un error.

La obsesión con microservicios viene de un lugar comprensible. Netflix, Spotify, Amazon — las empresas que más admiramos en tecnología llevan años evangelizando esta arquitectura. Los artículos en blogs técnicos, las charlas en conferencias y los hilos en Twitter repiten el mismo mensaje: los monolitos son legacy, los microservicios son el futuro.

Lo que esos artículos no cuentan es que Netflix empezó como un monolito. Spotify empezó como un monolito. Amazon empezó como un monolito. Migraron a microservicios cuando tenían cientos de ingenieros, millones de usuarios y necesidades de escalado que un monolito no podía satisfacer. No en la fase de MVP.

Por qué los monolitos ganan para MVPs

Un monolito es una aplicación desplegada como una unidad. Un repositorio, un proceso, una base de datos. Y para un MVP, eso es exactamente lo que necesitas por razones muy concretas:

Velocidad de desarrollo. En un monolito, un ingeniero puede implementar una funcionalidad end-to-end sin coordinar con otros servicios, sin gestionar comunicación entre procesos y sin preocuparse por consistencia de datos distribuidos. Llamas a una función, no a un endpoint HTTP. La diferencia en velocidad de iteración es brutal.

Simplicidad de despliegue. Un pipeline de CI/CD. Un servidor (o un contenedor). Un despliegue. No necesitas Kubernetes, service mesh, service discovery ni coordinación de versiones entre servicios. Cuando tu equipo es de 3-5 personas, esta simplicidad no es un lujo — es supervivencia.

Debugging directo. Cuando algo falla en un monolito, tienes un stack trace. Una ruta clara desde el error hasta la causa. En microservicios, un fallo puede propagarse a través de tres servicios distintos, con logs distribuidos en diferentes sistemas, latencias de red que oscurecen la causa raíz y fallos en cascada que convierten un bug simple en una investigación de horas.

Refactoring sin miedo. En un monolito, puedes mover código entre módulos, renombrar funciones y cambiar interfaces internas sin romper contratos de API entre servicios. Tu IDE te muestra todas las referencias. Tus tests cubren el flujo completo. En microservicios, un cambio en el schema de un evento puede romper tres servicios downstream sin que te enteres hasta que llega a producción.

Un solo modelo de datos. Una base de datos, un schema, una fuente de verdad. No necesitas decidir qué servicio es el "dueño" de la entidad usuario, no necesitas sincronizar datos entre servicios, no necesitas eventual consistency cuando tu producto todavía está definiendo qué datos necesita almacenar.

Cuándo los microservicios sí tienen sentido

Los microservicios resuelven problemas reales. Pero son problemas que la mayoría de MVPs no tienen:

Múltiples equipos trabajando en paralelo. Si tienes 30 ingenieros divididos en 6 equipos, un monolito se convierte en un cuello de botella. Los conflictos de merge son constantes, los despliegues requieren coordinación entre equipos y un error de un equipo puede bloquear el release de todos. Microservicios permiten que cada equipo despliegue de forma independiente.

Necesidades de escalado diferenciadas. Tu servicio de procesamiento de imágenes necesita GPUs y escala con el volumen de uploads. Tu API de búsqueda necesita mucha RAM y escala con el número de queries. Tu servicio de notificaciones es intensivo en I/O y escala con los usuarios activos. Si cada componente tiene patrones de escalado radicalmente diferentes, desplegarlos por separado permite optimizar recursos.

Requisitos tecnológicos distintos por servicio. Tu motor de recomendación funciona mejor en Python con ML libraries. Tu API de tiempo real necesita WebSockets en Node.js. Tu sistema de facturación requiere las garantías transaccionales de Java. Microservicios te permiten elegir la tecnología óptima para cada dominio.

¿Tu MVP tiene 30 ingenieros? ¿Necesitas escalar componentes de forma independiente? ¿Requieres tres lenguajes de programación diferentes? Probablemente no. Entonces no necesitas microservicios.

El sweet spot: el monolito modular

La mejor decisión para la mayoría de startups no es ni el monolito clásico (todo acoplado) ni los microservicios (todo separado). Es el monolito modular.

Un monolito modular se despliega como una unidad, pero internamente está organizado en módulos con límites claros. Cada módulo tiene su propia lógica de negocio, sus propios modelos de datos y una interfaz pública bien definida. Los módulos se comunican a través de interfaces internas — no llamadas HTTP, sino contratos de código.

Mantienes toda la simplicidad del monolito (un despliegue, una base de datos, debugging directo), pero con la modularidad que necesitas para escalar. Cuando llegue el momento de extraer un módulo como servicio independiente, los límites ya están definidos.

La clave es la disciplina. No llames directamente a las funciones internas de otro módulo. No compartas modelos de datos entre módulos. Usa la interfaz pública. La tentación de tomar atajos es constante cuando todo está en el mismo repositorio — y aquí es donde un ingeniero senior con experiencia en arquitectura marca la diferencia.

Los costes reales de los microservicios prematuros

Si todavía estás tentado por los microservicios para tu MVP, considera los costes que rara vez aparecen en los artículos que los promocionan:

Complejidad de DevOps. Cada servicio necesita su propio pipeline de CI/CD, su propia configuración de despliegue, su propio monitoreo. Con 5 microservicios, tienes 5 pipelines que mantener. Con un monolito, tienes uno.

Overhead de infraestructura. Kubernetes, service mesh, logging centralizado, tracing distribuido, health checks por servicio. Nada de esto es gratis — ni en dinero ni en tiempo de ingeniería.

Latencia de red. Lo que antes era una llamada a función en memoria (nanosegundos) ahora es una llamada HTTP o gRPC (milisegundos). Multiplica eso por cada interacción entre servicios en un request del usuario.

Consistencia de datos. Con una base de datos por servicio pierdes transacciones ACID entre servicios. Necesitas sagas o eventual consistency. Para un MVP que todavía está definiendo su modelo de datos, esto es complejidad prematura.

Debugging distribuido. Un bug que en un monolito se diagnostica en 15 minutos puede tomar medio día en microservicios. El error se originó en el servicio A, se propagó al B y el usuario lo vio en el C. Sin tracing distribuido bien configurado, estás navegando a ciegas.

Un framework de decisión simple

Antes de elegir arquitectura, responde estas preguntas:

  • ¿Tu equipo tiene menos de 8 ingenieros? → Monolito.
  • ¿Estás construyendo un solo producto? → Monolito.
  • ¿Estás en fase pre-seed, seed o Serie A temprana? → Monolito.
  • ¿Tu prioridad es velocidad de iteración y time-to-market? → Monolito.
  • ¿Puedes asumir el coste de un equipo de DevOps dedicado? → Si no, monolito.

Si has respondido "monolito" a todo: construye un monolito modular con límites claros entre módulos. Cuando tengas 20+ ingenieros, múltiples equipos y necesidades de escalado diferenciadas, estarás en posición de extraer servicios de forma incremental — sin reescribir desde cero.

Cómo diseñar un monolito que sea fácil de descomponer después

Si aceptas que el monolito es la decisión correcta hoy, la siguiente pregunta es cómo evitar que se convierta en una bola de barro que sea imposible de descomponer cuando llegue el momento. Estas son las prácticas que funcionan:

  • Organiza el código por dominio de negocio, no por capa técnica. En lugar de carpetas /controllers, /models, /services, usa /billing, /users, /notifications. Cada dominio contiene sus propios controladores, modelos y servicios.
  • Define interfaces explícitas entre módulos. Cada módulo expone una API interna (funciones, clases, interfaces) y oculta su implementación. Ningún módulo accede directamente a la base de datos de otro.
  • Una base de datos, pero schemas separados. Usa schemas o prefijos de tabla para separar los datos de cada módulo. Esto facilita la extracción futura.
  • Evita dependencias circulares. Si el módulo A depende de B y B depende de A, tienes un problema de diseño que será mucho peor cuando intentes separarlos.
  • Tests por módulo. Cada módulo tiene sus propios tests unitarios y de integración. Si puedes testear un módulo de forma aislada, puedes extraerlo de forma aislada.

Estas prácticas no requieren más tiempo de desarrollo. Requieren más disciplina de diseño. Y esa disciplina es lo que distingue a un ingeniero senior de uno junior — no el framework que usa, sino cómo estructura el código para que el equipo que viene después pueda trabajar con él.

En Conectia, los ingenieros senior que proporcionamos a startups europeas han construido y descompuesto monolitos en empresas de todos los tamaños. No llegan con una opinión dogmática sobre monolitos vs. microservicios — llegan con la experiencia para evaluar tu caso concreto y tomar la decisión correcta. Porque la arquitectura correcta no es la que está de moda. Es la que te permite entregar valor al usuario lo más rápido posible con el equipo que tienes hoy.


¿No tienes claro qué arquitectura necesita tu producto? Habla con un CTO — evaluamos tu caso y te recomendamos la arquitectura que se ajusta a tu etapa y tu equipo.

¿Listo para construir tu equipo de ingeniería?

Habla con un partner técnico y despliega ingenieros validados por CTOs en 72 horas.