Un monolito es una aplicación con un solo deploy; los microservicios la dividen en servicios pequeños, con deploys independientes, que se comunican por APIs. El debate suena arquitectónico, pero es sobre todo organizacional: la pregunta real es si tu estructura de equipos, tu conocimiento del dominio y tu madurez operativa pueden pagar la división — porque la división siempre cobra.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| Monolito | Un codebase, un deploy, llamadas in-process, una base de datos |
| Microservicios | Muchos servicios, deploys independientes, llamadas de red, una base de datos por servicio |
| La tercera opción escondida | El monolito modular — una sola unidad de deploy, fronteras internas aplicadas |
| Default de consenso | Empieza monolítico; divide cuando la coordinación de deploys duela, no antes |
| La trampa | El monolito distribuido — costos de microservicio con acoplamiento de monolito |
La diferencia en un ejemplo de código
Dentro de un monolito, llamar a otro módulo es una llamada de función — rápida, atómica e incapaz de fallar a medias:
// Monolito: llamada in-process — una transacción, un dominio de falla
const receipt = await billing.chargeOrder(order.id);
// Microservicios: la misma llamada cruza la red — y ahora eres dueño de
// timeouts, reintentos, fallas parciales y consistencia eventual
const res = await fetch('https://billing.internal/charge', {
method: 'POST',
body: JSON.stringify({ orderId: order.id }),
signal: AbortSignal.timeout(3000), // ¿y si billing está lento?
});
if (!res.ok) await compensateOrder(order.id); // ¿y si funcionó a medias?
Todo dolor de microservicios vive en esas tres últimas líneas. El camino del medio gestionado mantiene la lógica personalizada con deploy independiente sin entregarte el manejo de fallas — una función se llama como un servicio, pero corre en infraestructura gestionada por la plataforma:
// JavaScript / Node.js — Back4app JS SDK
// One deployable unit of business logic, no service mesh required
const receipt = await Parse.Cloud.run('chargeOrder', { orderId: 'ord_481' });
console.log(`Charged: ${receipt.status}`); // Flutter / Dart — Back4app Flutter SDK
final function = ParseCloudFunction('chargeOrder');
final response =
await function.execute(parameters: {'orderId': 'ord_481'});
if (response.success) {
print('Charged: ${response.result['status']}');
} // iOS / Swift — Back4app Swift SDK
ParseCloud.callFunction("chargeOrder",
parameters: ["orderId": "ord_481"]) { result in
if case .success(let receipt) = result {
print("Charged: \(receipt)")
}
} // Android / Kotlin — Back4app Android SDK
val params = hashMapOf("orderId" to "ord_481")
ParseCloud.callFunctionInBackground<Map<String, Any>>("chargeOrder", params) { receipt, e ->
if (e == null) Log.d("Billing", "Charged: ${receipt["status"]}")
} Tres formas, no dos
El artículo canónico de microservicios describe el destino; MonolithFirst describe el camino: casi todo sistema de microservicios exitoso empezó como un monolito que creció demasiado, y el monolito modular es cómo mantienes la opción abierta — fronteras primero, red después, y solo donde se la haya ganado.
Microservicios vs. monolito: las diferencias prácticas
| Dimensión | Monolito | Microservicios |
|---|---|---|
| Deploy | Una unidad, un tren de releases | Independiente, por servicio |
| Escalado | Toda la app escala junta | Por servicio, donde la carga realmente está |
| Llamadas entre partes | In-process, nanosegundos | Red, milisegundos + modos de falla |
| Consistencia de datos | Transacciones ACID | Sagas y consistencia eventual |
| Aislamiento de fallas | Un bug puede tumbarlo todo | Fallas contenidas — si el diseño lo prevé |
| Dónde vive la complejidad | En el código | En la operación |
| Encaje de equipo | Un equipo, hasta ~10 devs | Varios equipos autónomos |
| Debugging | Un stack trace | Tracing distribuido entre servicios |
| Perfil de costo | Un runtime, barato | Infra por servicio + observabilidad + equipo de plataforma |
La línea más afilada de esa tabla es dónde vive la complejidad: dividir un sistema no elimina complejidad — la reubica del codebase hacia la red, el pipeline de deploy y el dashboard de las 3 de la mañana.
Las dos direcciones de la historia de migración
La dirección famosa: una gran plataforma de streaming de video pasó años dividiendo su monolito en más de mil servicios, resolviendo un problema de escala que genuinamente tenía. La contracorriente es más reciente e igual de instructiva: la misma industria produjo un servicio de monitoreo que fusionó sus microservicios serverless de vuelta en un solo proceso y recortó los costos de infraestructura en cerca del 90% — mover datos entre las piezas era el gasto dominante — y equipos de ingeniería que consolidaron más de cien servicios de vuelta en uno, citando suites de tests y gestión de dependencias que se habían vuelto inmanejables. Ambas direcciones fueron racionales: la constante es que la arquitectura siguió al problema medido, no a la tendencia.
Casos de uso comunes
- Monolito: productos nuevos, equipos pequeños, dominios todavía difusos — cualquier lugar donde la velocidad de aprendizaje vale más que la teoría de escalado.
- Monolito modular: productos en crecimiento que quieren opciones futuras sin overhead presente; el default que vale la pena defender.
- Microservicios: muchos equipos publicando de forma independiente, componentes con escalados divergentes (feed vs. checkout), organizaciones que ya operan aprovisionamiento rápido, monitoreo y guardias.
- Híbrido con backend gestionado: funciones estándar (auth, datos, almacenamiento) consumidas como servicio, lógica personalizada como funciones con deploy independiente — autonomía de nivel de servicio a costo de ops de monolito.
¿Deberías dividir? Matriz de decisión
| Sigue monolítico cuando… | Divide cuando… |
|---|---|
| El equipo cabe en una sala (< ~10 devs) | 15–20+ devs en varios equipos hacen fila en un solo release |
| Las fronteras de dominio todavía cambian cada mes | Las fronteras llevan trimestres estables |
| Las transacciones atraviesan tus workflows centrales | Los componentes tienen datos genuinamente independientes |
| Madurez de ops = “a veces hacemos deploy” | El aprovisionamiento, el tracing y las guardias ya son sólidos |
| El dolor es la calidad del código | El dolor es la coordinación de deploys |
Si la columna izquierda te describe pero la derecha te tienta, el monolito modular es el compromiso honesto — y si divides y descubres que cada cambio toca tres servicios, construiste el monolito distribuido y deberías fusionar de vuelta sin ninguna vergüenza.
Limitaciones y trade-offs
- Monolito: el tren de releases se frena a medida que los equipos se multiplican; una fuga de memoria es la caída de todos; las marañas viejas resisten la extracción si la disciplina de módulos se relaja.
- Microservicios: el “MicroservicePremium” — transacciones distribuidas, manejo de fallas de red, APIs versionadas entre tus propios equipos y un stack de observabilidad que se convierte en su propia línea del presupuesto.
- Ambos: ninguno arregla un dominio mal modelado. Fronteras de servicio trazadas sobre un mal modelo producen una versión distribuida del mismo desorden, con latencia.
- La restricción organizacional es real: por la ley de Conway, publicas tu estructura de comunicación. Reestructurar la arquitectura sin reestructurar los equipos produce el antipatrón con toda confiabilidad.
Microservicios vs. monolito en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Cambia los términos del debate: el 80% estándar del backend ni siquiera es tuyo para arquitectar, y el 20% personalizado corre como funciones Cloud Code — cada una con deploy independiente como un microservicio, ninguna cargando un service mesh, una base de datos por servicio ni una rotación de guardias. Los equipos que crecen incluso más allá de eso conservan la salida: el stack es open source, así que extraer un servicio de verdad más adelante parte de fronteras que ya funcionan, no de una reescritura.
Preguntas frecuentes
¿Qué es mejor: microservicios o monolito?
Ninguno en términos universales — optimizan cosas distintas. El monolito optimiza la simplicidad: un codebase, un deploy, llamadas in-process, transacciones de base de datos de verdad. Los microservicios optimizan la autonomía de los equipos y el escalado independiente — al precio de la complejidad de los sistemas distribuidos. Lo que decide son el tamaño del equipo, la estabilidad del dominio y la madurez operativa, no la moda arquitectónica.
¿Una startup debería usar microservicios?
El consenso fuerte de la industria es que no — empieza con un monolito. El argumento canónico, del ensayo MonolithFirst de Martin Fowler, observa que casi toda historia de éxito con microservicios comenzó como un monolito que creció demasiado, mientras que los sistemas nacidos como microservicios sufren: terminas trazando las fronteras de los servicios antes de entender el dominio — justo cuando vas a trazarlas mal.
¿Qué es un monolito modular?
La tercera opción, deliberadamente aburrida: una sola aplicación desplegable con fronteras internas de módulo aplicadas con rigor. Conserva la simplicidad operativa del monolito mientras construye las costuras que hacen posible una división futura — y es el default recomendado por consenso para la mayoría de los equipos, porque los módulos bien trazados pueden extraerse como servicios después; un monolito enredado, no.
¿Qué es un monolito distribuido?
El antipatrón que combina lo peor de ambos mundos: servicios físicamente separados que deben cambiarse y desplegarse juntos — casi siempre porque las fronteras se trazaron mal o porque los servicios comparten una base de datos. Pagas los costos operativos de los microservicios (llamadas de red, orquestación, observabilidad) conservando el acoplamiento del monolito. Es el modo de falla más común de la división prematura.
¿Cuándo dividir un monolito en microservicios?
Cuando la coordinación de deploys — no el tamaño del código — se vuelve el cuello de botella: varios equipos haciendo fila en un único tren de releases, componentes con necesidades de escalado genuinamente divergentes y fronteras de dominio que dejaron de moverse. Umbrales prácticos de la industria: por debajo de unos diez desarrolladores, el monolito casi siempre es lo correcto; la división empieza a pagarse a partir de quince desarrolladores en varios equipos.
¿Cómo manejan los microservicios la consistencia de datos?
Con dificultad — este es el costo menos publicitado. Cada servicio es dueño de su base de datos, así que la transacción ACID que era una línea en el monolito se convierte en una saga: una secuencia de transacciones locales con rollbacks compensatorios, que se asienta en consistencia eventual. Los workflows que de verdad necesitan actualizaciones atómicas entre servicios son una señal de que esos servicios no debieron separarse.
¿Qué tiene que ver la ley de Conway con esta decisión?
Todo — los sistemas terminan reflejando la estructura de comunicación de las organizaciones que los construyen. Los microservicios funcionan cuando equipos pequeños y autónomos son dueños de un servicio de punta a punta; la arquitectura es tanto un organigrama como un diagrama. Un único equipo pequeño que adopta microservicios gana el overhead de coordinación de muchos equipos sin tenerlos.
¿Hay empresas que volvieron de los microservicios al monolito?
Sí, y los casos son instructivos. El equipo de monitoreo de una gran plataforma de video fusionó — de forma célebre — sus microservicios serverless de vuelta en un solo proceso y recortó cerca del 90% de los costos de infraestructura: mover datos entre las piezas era el gasto dominante. Otros equipos de ingeniería consolidaron cientos de microservicios en un único servicio, citando sobrecarga de tests y dependencias. La lección no es que "los microservicios están mal", sino que la división debe pagar su propio overhead.