Módulo 2: La Ley de Conway

3. El monolito es tu primer organigrama

Descripción

Al terminar esta lección vas a entender de dónde salió ese 61.5% de dependencias cross-equipo que mediste en Mercado —y con él, el origen de casi todo monolito doloroso que verás en tu carrera—. La respuesta es incómoda y liberadora a la vez: el monolito de Mercado no está mal diseñado; está perfectamente diseñado para una organización que ya no existe. Cuando Mercado era un solo equipo de siete personas, un monolito era la arquitectura correcta: cero fronteras internas que coordinar, comunicación gratis entre todas las partes, un despliegue simple. El monolito era el reflejo fiel de un equipo único, y por eso funcionaba. El dolor de hoy no viene de que el monolito sea malo, sino de que la organización cambió y el código no la siguió: el negocio se partió en cinco squads, pero el código siguió siendo el mismo bloque, y ahora cinco equipos intentan poseer por pedazos algo que fue diseñado para un dueño único. Vas a medir esto ejecutando: la misma base de código, sin cambiar una línea, pasa de estar perfectamente alineada (0 dependencias cross-team con un equipo) a estar rota (8 dependencias cross-team con cinco squads).

Esto importa porque cambia cómo diagnosticas un monolito problemático —y qué haces al respecto—. El instinto del ingeniero es culpar al código: "está mal modularizado", "los que lo escribieron no sabían de arquitectura". Casi siempre es injusto. El código estaba bien modularizado para su organización original; lo que se rompió fue la correspondencia entre el código y una organización nueva. Y ese diagnóstico cambia la cura. Si el problema fuera el código, la solución sería reescribirlo. Pero como el problema es el desalineamiento entre un código de un-equipo y una organización de cinco-equipos, reescribir el código sin arreglar el desalineamiento solo produce un monolito nuevo con el mismo problema en unos meses. Aquí aparece el error más caro del módulo, el que vas a ver medido: reorganizar los equipos sin reorganizar el código —partir la gente en squads y dejar el monolito intacto— produce lo que Mercado tiene hoy: un sistema que pelea contra su propia organización, con la fricción máxima y sin las ventajas de ninguna de las dos formas.

Conexión con el módulo: esta lección es la historia de origen. La lección 2 midió el síntoma (61.5% cross-equipo, hoy); esta explica la causa (el código nació para un equipo y la organización se multiplicó). Usa exactamente el mismo mapa de dependencias de la lección 2 —las mismas trece— pero lo mide bajo dos organizaciones distintas, para aislar la única variable que cambió: quién es dueño de qué. Y prepara las dos lecciones de cura: entender que el monolito refleja un equipo pasado es lo que justifica la maniobra inversa (lección 6) —alinear la organización con la arquitectura que quieres— y las team topologies (lección 7) —diseñar equipos que produzcan las fronteras correctas—. Si la lección 2 fue "aquí está el desalineamiento", esta es "así se metió, y así se evita meterlo".

La casa que se construyó para una familia y hoy la habitan cinco

Piénsalo así. Una pareja construye una casa. Como son dos, la diseñan abierta: un gran espacio único donde la cocina, la sala y el comedor fluyen sin paredes, porque entre ellos dos no hace falta privacidad —comparten todo, se oyen desde cualquier rincón, y una casa sin muros internos es más barata, más luminosa y más fácil de mantener—. Para una pareja, el plano abierto es el diseño correcto. No es descuido: es la forma óptima para esa organización de dos personas.

Pasan los años. La familia crece: llegan hijos, se muda la abuela, después la hermana con su pareja. Ahora viven cinco adultos y tres niños en la misma casa de plano abierto. Y de repente el diseño que era perfecto se vuelve un tormento: no hay dónde tener una llamada sin que todos escuchen, la abuela quiere silencio a las nueve y los adolescentes quieren música, nadie tiene un espacio propio. La casa no se volvió mala; se volvió inadecuada para una familia que ya no es la de dos personas que la diseñó. El plano abierto era el reflejo de una pareja, y ahora lo habita una organización de ocho.

¿Qué hacen? Aquí está la parte importante. Si solo reparten las habitaciones existentes —"esta esquina es tuya, esa es mía"— sin construir paredes, no resuelven nada: siguen oyéndose todos, siguen sin privacidad, solo que ahora con la ilusión de que "cada quien tiene su zona". Eso es exactamente lo que hace una empresa que parte a la gente en squads pero deja el monolito intacto: reparte el ownership de un espacio abierto sin construir los muros que harían real la separación. La solución de verdad es levantar paredes —crear fronteras internas donde antes no hacían falta—, y eso es caro, molesto y hay que hacerlo a propósito. En software, levantar paredes es modularizar el código para que cada squad tenga su espacio de verdad; y —la lección del módulo— hacerlo junto con la reorganización de equipos, no una sin la otra.

Ejemplo trabajado: el mismo código, dos organizaciones

Vamos a medir el corazón de la historia. Tomamos las mismas trece dependencias de Mercado que usamos en la lección 2 —el código no cambia—, y las medimos bajo dos organizaciones: la de 2019 (un solo equipo, core-team, dueño de todo) y la de 2024 (los cinco squads). La única variable que se mueve entre las dos filas es el mapa de ownership. Todo lo demás —los módulos, sus dependencias— es idéntico. Si las dependencias cross-equipo cambian, la causa no puede ser el código: solo cambió la organización.

# Por que el monolito de Mercado refleja que al principio habia UN solo equipo.
# Medimos la misma base de codigo bajo dos organizaciones distintas.

deps = [
    ("search",             "product_catalog"),
    ("cart",               "product_catalog"),
    ("checkout",           "cart"),
    ("checkout",           "payment_processing"),
    ("checkout",           "shipping_labels"),
    ("checkout",           "notifications"),
    ("checkout",           "order_processing"),
    ("order_processing",   "shipping_labels"),
    ("order_processing",   "auth"),
    ("payment_processing", "invoicing"),
    ("payment_processing", "auth"),
    ("invoicing",          "notifications"),
    ("shipping_labels",    "delivery_tracking"),
]

def cross_team_deps(owner):
    """Cuantas dependencias del codigo cruzan una frontera de equipo."""
    return sum(1 for s, d in deps if owner[s] != owner[d])

modules = [
    "product_catalog", "search", "cart", "order_processing", "checkout",
    "payment_processing", "invoicing", "shipping_labels", "delivery_tracking",
    "auth", "notifications",
]

# FASE 1 (genesis, 2019): un solo equipo escribe todo el monolito.
owner_genesis = {m: "core-team" for m in modules}

# FASE 2 (hoy, 2024): el negocio se partio en 5 squads por dominio...
# ...pero el CODIGO siguio siendo el mismo monolito enredado.
owner_today = {
    "product_catalog": "catalog",   "search": "catalog",
    "cart": "orders",               "order_processing": "orders",
    "checkout": "orders",
    "payment_processing": "payments", "invoicing": "payments",
    "shipping_labels": "shipping",  "delivery_tracking": "shipping",
    "auth": "platform",             "notifications": "platform",
}

total = len(deps)
c1 = cross_team_deps(owner_genesis)
c2 = cross_team_deps(owner_today)

print(f"{'organizacion':<28}{'equipos':>8}{'cross-team deps':>18}{'alineacion':>13}")
print(f"{'FASE 1  (1 equipo, 2019)':<28}{1:>8}{c1:>15}/{total:<2}{(1-c1/total)*100:>11.1f}%")
print(f"{'FASE 2  (5 squads, 2024)':<28}{5:>8}{c2:>15}/{total:<2}{(1-c2/total)*100:>11.1f}%")
print()
print(f"El codigo NO cambio una sola linea entre las dos filas.")
print(f"Solo cambio quien es dueno de que. Las dependencias cross-team")
print(f"saltaron de {c1} a {c2}: el monolito, perfecto para 1 equipo,")
print(f"pelea contra los 5 squads que hoy intentan poseerlo por pedazos.")

Qué esperar. Al correrlo:

organizacion                 equipos   cross-team deps   alineacion
FASE 1  (1 equipo, 2019)           1              0/13      100.0%
FASE 2  (5 squads, 2024)           5              8/13       38.5%

El codigo NO cambio una sola linea entre las dos filas.
Solo cambio quien es dueno de que. Las dependencias cross-team
saltaron de 0 a 8: el monolito, perfecto para 1 equipo,
pelea contra los 5 squads que hoy intentan poseerlo por pedazos.

Detente en las dos filas, porque son la historia de origen del dolor de Mercado en dos renglones.

Fila 1 — 2019, un equipo: alineación perfecta. Con core-team dueño de los once módulos, cero dependencias cruzan una frontera de equipo, porque no hay fronteras que cruzar: todo es del mismo equipo. La alineación es 100%. El monolito era, literalmente, la arquitectura perfectamente conwayana para un equipo único —cada dependencia es intra-equipo, coordinación gratis, sin junturas frágiles porque no hay junturas entre organizaciones—. Cualquiera que en 2019 hubiera dicho "esto debería ser cinco microservicios" habría estado equivocado: habría añadido cinco fronteras de coordinación a un equipo que no las necesitaba, puro costo sin beneficio. El monolito no era deuda técnica; era la decisión correcta.

Fila 2 — 2024, cinco squads: alineación rota. El código es idéntico —las mismas trece dependencias, byte por byte—, pero ahora repartido entre cinco squads. De golpe, ocho de las trece dependencias cruzan fronteras de equipo, y la alineación se desploma de 100% a 38.5%. No se escribió ni se borró una línea; solo se dibujó un mapa nuevo de quién posee qué. Ese salto de 0 a 8 es el nacimiento del monolito doloroso: el mismo código que fue perfecto para un equipo se volvió una fuente de fricción para cinco, porque ahora cada una de esas ocho dependencias exige que dos squads coordinen algo que antes una sola persona hacía sin pedirle permiso a nadie.

Aquí está la lección central hecha número: el monolito no se degradó, se desalineó. El código no empeoró entre 2019 y 2024; lo que cambió fue la organización que intenta poseerlo. El monolito de Mercado es, en el sentido más literal, el organigrama de 2019 fosilizado en código —una foto de cuando eran un equipo, que la empresa sigue cargando aunque ya sea cinco—. Por eso decimos que el monolito es tu primer organigrama: la estructura de tu primer sistema es un molde de tu primera organización, y ese molde se queda mucho después de que la organización cambió.

Y aquí está el error caro, medido: la fila 2 es exactamente lo que produce reorganizar los equipos sin reorganizar el código. La empresa hizo la mitad del trabajo —partió a la gente en squads (fácil: es un correo y un cambio en la herramienta de RR.HH.)— pero no la otra mitad —partir el código en módulos con dueños claros (difícil: es meses de refactorización)—. El resultado es el peor de los mundos: tienen la coordinación cara de cinco equipos (todos tienen que ponerse de acuerdo) sin la independencia que justificaría esa coordinación (nadie puede desplegar sin pisar a otro). Un solo equipo con un monolito coordina barato. Cinco equipos con cinco servicios coordinan poco y despliegan independiente. Cinco equipos con un monolito coordinan caro y no despliegan independiente —lo peor de ambos—. Ese 38.5% es la firma de esa mitad-de-trabajo.

Profundización: por qué el monolito es la elección correcta al principio (y cuándo deja de serlo)

Es tentador leer esta lección como "los monolitos son malos, hay que nacer con microservicios". Sería la lección equivocada, y peligrosa. La verdad es más sutil y más útil: el monolito es casi siempre la arquitectura correcta al principio, precisamente por Conway.

Cuando un producto arranca, la organización es chica —un equipo, a veces una sola persona—. Para esa organización, las fronteras de servicio son puro costo: cada servicio separado añade una red que puede fallar, un contrato que versionar, un despliegue que orquestar, y sobre todo una frontera de coordinación que, dentro de un solo equipo, no compra nada —porque la coordinación ya era gratis, todos se sientan juntos—. Nacer con microservicios cuando eres tres personas es como que la pareja construya la casa con ocho recámaras separadas "por si acaso crece la familia": pagas hoy el costo de mantener ocho espacios cuando solo necesitas uno abierto, y probablemente el producto muere (o pivotea) antes de que la familia crezca. Es sobre-ingeniería, y Conway lo explica: le pusiste al sistema fronteras que tu organización no tiene, así que esas fronteras solo estorban.

El monolito deja de ser correcto cuando la organización cruza cierto tamaño y la coordinación interna empieza a doler más de lo que dolerían las fronteras. Ese punto llega —lo vas a cuantificar en la lección 4— cuando los canales de comunicación dentro del equipo grande crecen tanto que la gente pasa más tiempo coordinando que construyendo. Ahí es cuando partir en equipos (y en servicios que reflejen esos equipos) empieza a valer la pena: cambias el costo de coordinación interna por el costo de las fronteras, y a cierta escala las fronteras salen más baratas. La señal no es "llegamos a X líneas de código" ni "microservicios están de moda"; es "el equipo se volvió demasiado grande para coordinar como uno solo", que es una señal organizacional, no técnica.

El error de Mercado no fue nacer con un monolito —eso estuvo bien—. Fue crecer la organización sin evolucionar la arquitectura al mismo tiempo. Cuando partieron a la gente en cinco squads, ese era el momento de empezar a partir el monolito en módulos (o servicios) alineados a esos squads. Hacer una cosa sin la otra los dejó atrapados en la fila 2. La lección para tu carrera: cada vez que tu organización cambie de forma —contratas, te partes en equipos, fusionas dos grupos—, pregúntate si la arquitectura tiene que cambiar de forma con ella. Porque si la organización se mueve y el sistema no, Conway garantiza que vas a terminar con un sistema que refleja una organización que ya no existe —tu primer organigrama, fosilizado, peleando contra el actual—.

Errores comunes

Culpar al código en vez de al desalineamiento (de diagnóstico). Qué pasa: el equipo ve el monolito doloroso y concluye "está mal escrito, hay que reescribirlo", y se lanza a un reescritura de dos años. Reescriben, lanzan el monolito nuevo... y en un año duele igual, porque no tocaron la causa. Por qué pasa: es más fácil y más satisfactorio culpar al código (que se puede reescribir) que a la estructura organizacional (que parece intocable). Cómo detectarlo: si tu plan para arreglar un monolito no menciona en absoluto la organización de equipos, estás tratando el síntoma. Cómo corregirlo: mide el desalineamiento (la fila 2); si el código estaba bien para un equipo y se rompió al partirse en cinco, la cura incluye reorganizar los equipos, no solo el código.

Reorganizar los equipos sin reorganizar el código (de mitad-de-trabajo). Qué pasa: la empresa parte a la gente en squads por dominio pero deja el monolito intacto, y se sorprende de que todo se volvió más lento en vez de más rápido. Por qué pasa: partir gente es barato y visible (un anuncio); partir código es caro y lento (meses de refactor), así que se hace lo primero y se pospone lo segundo "para después" —y después nunca llega—. Cómo detectarlo: si tienes N equipos pero un solo despliegue donde todos se pisan, hiciste media reorganización; el número que lo delata es una alta proporción de dependencias cross-equipo (Mercado: 61.5%). Cómo corregirlo: la reorganización de equipos y la de código van juntas o no van —o construyes las paredes cuando repartes las habitaciones, o solo creaste la ilusión de zonas—.

Nacer con microservicios "por si acaso" (de sobre-ingeniería, el error opuesto). Qué pasa: un equipo de tres personas arranca un producto nuevo con doce microservicios "para estar preparados para escalar", y se ahogan en la complejidad de operar doce servicios para un producto que aún no tiene usuarios. Por qué pasa: confunden "microservicios son buenos a escala" con "microservicios son buenos siempre", e ignoran que las fronteras que su organización no necesita solo cuestan. Cómo detectarlo: si tienes más servicios que equipos —o más servicios que developers—, casi seguro sobre-fragmentaste. Cómo corregirlo: nace con el monolito (bien modularizado por dentro), que es la arquitectura conwayana correcta para un equipo chico, y parte en servicios cuando la organización crezca lo suficiente para justificar las fronteras —ni antes (sobre-ingeniería) ni mucho después (el atraso de Mercado)—.

Ejercicios

Ejercicio 1 — La fase intermedia. El ejemplo mide 2019 (1 equipo) y 2024 (5 squads). Imagina un punto intermedio, 2021, cuando Mercado se partió en solo dos equipos: commerce (dueño de product_catalog, search, cart, order_processing, checkout, payment_processing, invoicing) y logistics-platform (dueño de shipping_labels, delivery_tracking, auth, notifications). Sin correr el código, cuenta cuántas de las trece dependencias cruzarían la frontera entre esos dos equipos.

Ver solución

Con dos equipos, una dependencia cruza solo si su origen y su destino están en equipos distintos. commerce = {product_catalog, search, cart, order_processing, checkout, payment_processing, invoicing}; logistics-platform = {shipping_labels, delivery_tracking, auth, notifications}. Revisamos las trece:

  1. search -> product_catalog: commerce → commerce. Intra.
  2. cart -> product_catalog: commerce → commerce. Intra.
  3. checkout -> cart: commerce → commerce. Intra.
  4. checkout -> payment_processing: commerce → commerce. Intra.
  5. checkout -> shipping_labels: commerce → logistics-platform. CROSS.
  6. checkout -> notifications: commerce → logistics-platform. CROSS.
  7. checkout -> order_processing: commerce → commerce. Intra.
  8. order_processing -> shipping_labels: commerce → logistics-platform. CROSS.
  9. order_processing -> auth: commerce → logistics-platform. CROSS.
  10. payment_processing -> invoicing: commerce → commerce. Intra.
  11. payment_processing -> auth: commerce → logistics-platform. CROSS.
  12. invoicing -> notifications: commerce → logistics-platform. CROSS.
  13. shipping_labels -> delivery_tracking: logistics-platform → logistics-platform. Intra.

Seis dependencias cruzan (las 5, 6, 8, 9, 11, 12). Alineación = (13−6)/13 ≈ 53.8%.

La lección: con dos equipos bien elegidos, el desalineamiento (6 cross, 53.8%) es menor que con cinco squads mal alineados (8 cross, 38.5%). No es el número de equipos lo que crea la fricción, sino qué tan bien las fronteras de los equipos coinciden con las junturas naturales del código. Dos equipos cuyas fronteras respetan los clústeres del código pueden estar mejor alineados que cinco squads cuyas fronteras los parten a la mitad. Esto anticipa la maniobra inversa: se trata de elegir las fronteras correctas, no las más.

Ejercicio 2 — El monolito que sí estaba bien. Un colega, al ver el 100% de alineación de 2019, dice: "entonces en 2019 tenían la arquitectura perfecta y la arruinaron". ¿En qué tiene razón y en qué se equivoca? ¿La arquitectura de 2019 seguiría siendo "perfecta" si Mercado hubiera crecido a cincuenta ingenieros manteniéndose como un solo equipo?

Ver solución

En qué tiene razón: la arquitectura de 2019 sí era la correcta para su organización de entonces. Un monolito con 100% de dependencias intra-equipo es la forma conwayana óptima para un equipo único —cero fronteras que coordinar, máxima velocidad—. Nacer con microservicios ahí habría sido un error de sobre-ingeniería.

En qué se equivoca: en dos cosas. Primero, la palabra "perfecta" es engañosa: la arquitectura no era perfecta en abstracto, era perfecta para esa organización. "Perfecto" siempre es relativo a la organización, igual que "el mejor auto" es relativo a para qué lo quieres. Segundo, y más importante: no la "arruinaron" cambiando el código —el código sigue igual—; el desalineamiento lo causó cambiar la organización sin evolucionar la arquitectura. Culpar el deterioro es como culpar a la pareja por su casa de plano abierto cuando la familia creció: la casa no se arruinó, se volvió inadecuada para una familia nueva.

¿Seguiría siendo perfecta con cincuenta ingenieros en un solo equipo? No, y esta es la clave. Aunque mantuvieran un solo equipo (y por tanto 100% de alineación técnica intra-equipo), cincuenta personas en un equipo es una catástrofe de coordinación —lo vas a cuantificar en la lección 4: cincuenta personas son 1225 canales de comunicación—. El monolito seguiría "alineado" en el sentido de Conway, pero la organización de cincuenta-en-uno sería inviable. O sea: la arquitectura de 2019 no escala ni siquiera manteniendo un equipo, porque el problema a esa escala no es el desalineamiento código↔organización, sino que la organización misma (un equipo gigante) no funciona. El monolito de 2019 era correcto para siete personas, no para cincuenta —bajo ninguna organización—.

Ejercicio 3 — Diseña la evolución que faltó. Sabiendo lo que sabes, ¿qué debió hacer Mercado en el momento de partir a la gente en cinco squads para no terminar en la fila 2? Describe el trabajo que faltó y por qué tenía que ir de la mano con la reorganización, no después.

Ver solución

Lo que faltó fue evolucionar la arquitectura al mismo tiempo que la organización: cuando partieron a la gente en los cinco squads, debieron empezar a partir el monolito en módulos (o servicios) con fronteras que coincidieran con los squads. En concreto:

  1. Dar a cada squad un módulo (o servicio) del que sea dueño único, con una API clara hacia los demás. product_catalog+search para catalog; el flujo de pedido para orders; el cobro para payments; etc. Que cada squad pueda cambiar y desplegar su pedazo sin pedir permiso a los otros.
  2. Extraer las capacidades transversales (auth, notifications) a un squad de plataforma que las ofrezca como servicio estable, para que los demás las consuman sin coordinar cada cambio —el modo x-as-a-service de la lección 7—.
  3. Atacar el punto de mayor cruce primero: el checkout, que cruza hacia payments, shipping y platform. Decidir quién lo posee y darle una frontera limpia (la lección 5 mide por qué es el peor, y la 6 lo resuelve).

Por qué de la mano y no después: porque si reorganizas los equipos y pospones la reorganización del código, entras en la fila 2 —el peor de los mundos— y te quedas ahí. El "después" no llega: una vez que tienes cinco equipos peleándose el monolito, cada uno está tan ocupado apagando los incendios de la coordinación cara que nadie tiene tiempo para el refactor grande, y la fricción se vuelve permanente. La ventana para evolucionar la arquitectura es cuando cambias la organización, no meses más tarde. Reorganizar equipos y arquitectura son las dos mitades de un mismo movimiento; separarlas en el tiempo es la trampa. (La forma disciplinada de hacer este movimiento a propósito es la maniobra inversa de Conway, lección 6.)

Resumen y siguiente paso

En esta lección descubriste el origen del monolito doloroso: el monolito es tu primer organigrama, fosilizado en código. Con la casa de plano abierto viste que un diseño puede ser perfecto para la organización que lo creó y volverse un tormento para la que la habita después, sin que el diseño haya cambiado —lo que cambió fue la organización—. Y lo mediste ejecutando: las mismas trece dependencias de Mercado pasan de 0 cross-equipo (100% de alineación con un equipo, en 2019) a 8 cross-equipo (38.5%, con cinco squads, en 2024), sin que el código cambie una línea. Entendiste que el monolito no se degradó sino que se desalineó, que nacer con un monolito es casi siempre correcto (y nacer con microservicios es sobre-ingeniería), y que el error caro de Mercado fue reorganizar los equipos sin reorganizar el código —quedarse en el peor de los mundos: la coordinación cara de cinco equipos sin la independencia de cinco servicios—.

Antes de avanzar deberías poder: explicar por qué un monolito puede estar perfectamente diseñado para una organización y ser un tormento para otra; medir el desalineamiento midiendo el mismo código bajo dos organizaciones; y reconocer el error de mitad-de-trabajo (partir la gente sin partir el código) y por qué las dos mitades van juntas.

Lo que sigue es la razón económica de todo esto: por qué crecer la organización sin partirla en equipos chicos se vuelve insostenible, y por qué las fronteras empiezan a valer la pena a cierta escala. En la lección 4 vas a ejecutar la fórmula de los communication pathsn(n-1)/2— y ver el costo de coordinación explotar de forma cuadrática: 2 personas necesitan 1 canal, 10 necesitan 45, 50 necesitan 1225. Vas a ver, en números, por qué un equipo de cincuenta es inviable y por qué partir en equipos chicos baja la coordinación por un factor enorme con la misma gente. Es el motor que hace que la Ley de Conway tenga consecuencias tan caras —y la justificación cuantitativa de los equipos pequeños—.

Recursos