Comparación honesta: metadatos, complejidad y topología
OT guarda el documento y paga en corrección y en topología, los CRDT guardan identidad e historia y pagan en metadatos; medir las tres monedas por separado explica por qué OT sigue vivo y dónde deja de servir.
Las cuatro lecciones anteriores han presentado dos escuelas que resuelven el mismo problema histórico disolviendo premisas distintas, y la tentación evidente al llegar aquí es declarar una ganadora. Conviene resistirla, no por diplomacia sino porque la comparación en abstracto no tiene respuesta: las dos familias pagan en monedas diferentes y ninguna moneda domina a la otra en todos los productos. Esta lección separa las tres facturas que de verdad importan —tamaño de los metadatos, complejidad de la implementación y requisitos de topología— y las examina una por una, porque mezclarlas es exactamente lo que produce las comparativas inútiles que circulan. Al final aparecen las dos preguntas que sí discriminan en un caso concreto, un inventario de dónde OT sigue siendo la elección correcta, y el adelanto de un trabajo reciente que ocupa deliberadamente el terreno intermedio entre ambas.
- Separar las tres facturas y evitar el error de comparar sistemas midiendo una sola de ellas.
- Entender por qué OT guarda el documento y los CRDT guardan su historia, y qué implica esa asimetría.
- Reconocer que la complejidad no es mayor en una familia sino que está localizada en sitios distintos.
- Identificar los contextos donde OT sigue siendo la decisión correcta y los que exigen la otra escuela.
Metadatos: el documento frente a su historia
La primera factura es la más citada y la peor entendida. Un sistema OT clásico guarda el documento actual más un buffer de operaciones recientes que puede podarse en cuanto todos los participantes han confirmado una revisión, de modo que su estado en reposo es proporcional al contenido y no a la cantidad de ediciones que lo produjeron. Un documento de cien kilobytes con diez años de historia ocupa cien kilobytes. Esa propiedad es genuinamente valiosa y es la ventaja estructural más sólida que la familia conserva.
Un CRDT guarda algo distinto por necesidad, no por descuido. Para que un identificador sirva de ancla estable tiene que existir mientras alguien pueda referirse a él, y para que un elemento borrado siga sirviendo de ancla su marca de muerte tiene que sobrevivir al dato. El estado en reposo es por tanto proporcional a la historia: los identificadores pesan, las marcas de borrado se acumulan y un documento muy editado guarda mucho más de lo que muestra. Las cifras que circulan sobre sobrecostes de uno o dos órdenes de magnitud provienen de implementaciones tempranas que asignaban una estructura completa por carácter, y sería deshonesto presentarlas como el estado actual del arte.
// Ingenuo: una estructura por caracter, identidad completa en cada uno
const ingenuo = [
{ id: "r1.1", valor: "h", muerto: false },
{ id: "r1.2", valor: "o", muerto: false },
{ id: "r1.3", valor: "l", muerto: false },
];
// Compactado: las inserciones contiguas de una replica son un solo tramo
const compactado = [
{ replicaBase: "r1", contadorBase: 1, texto: "hola mundo", muertos: [] },
];
// Escribir de izquierda a derecha, que es como escribe la gente,
// produce tramos largos y el coste por caracter tiende a desaparecer
Hay además una asimetría que se pasa por alto y que juega a favor de la familia convergente en el caso que más importa aquí. El estado de OT es pequeño solo mientras el servidor pueda podar, y podar exige saber que todos los participantes han confirmado una revisión. Un producto con soporte serio para trabajo desconectado no puede podar con libertad, porque cualquier cliente que lleve semanas fuera podrá aparecer con operaciones referidas a un contexto antiguo; para atenderlo hay que conservar el historial desde entonces, y el estado de OT deja de ser proporcional al documento y pasa a serlo a la ventana de desconexión tolerada. La ventaja estructural de OT en metadatos, por tanto, se estrecha exactamente en el escenario local-first y es máxima en el escenario conectado.
La observación que reconcilia las dos cifras es que las ediciones humanas son extraordinariamente regulares: la gente escribe de izquierda a derecha, en rachas, y eso produce secuencias largas de identificadores consecutivos de la misma réplica. Las implementaciones modernas explotan esa regularidad codificando tramos en vez de elementos y comprimiendo por columnas, con lo que el coste amortizado por carácter baja de forma drástica. La factura no desaparece —la identidad y las marcas siguen ahí, y un documento editado de forma muy dispersa por muchas réplicas sigue siendo caro— pero deja de ser el argumento decisivo que fue durante una década.
Las tres magnitudes se confunden constantemente y responden a decisiones independientes. El coste en reposo depende del formato de serialización y admite compresión agresiva. El coste en memoria depende de las estructuras que la implementación construye para responder rápido a las consultas, y puede ser mucho mayor o mucho menor que el anterior. El coste en red depende de qué se transmite: estados completos, deltas o solo operaciones nuevas. Una biblioteca puede ser excelente en una de las tres y mediocre en las otras dos, y las comparativas que publican un único número casi siempre están midiendo la que mejor le sienta al sistema que defienden.
Complejidad: no es más, es en otro sitio
La segunda factura se enuncia mal casi siempre. La afirmación de que los CRDT son más simples que OT es falsa si se toma como enunciado sobre cantidad de código: una secuencia convergente con recolección de marcas y consultas eficientes por posición es un artefacto considerable, y las implementaciones serias de esta familia no son pequeñas. Lo que cambia no es el volumen de dificultad sino su distribución y su modo de verificación.
En OT, la dificultad está repartida por toda la matriz de transformación, crece con el cuadrado de los tipos de operación y su corrección es una propiedad global: añadir un tipo obliga a revisar una fila y una columna, y la propiedad que garantiza la convergencia con tres o más concurrentes es la que la lección dos mostró que resistió durante años a la revisión por pares. En un CRDT, la dificultad está concentrada en la definición de cada tipo, su corrección es local y se compone: un mapa de conjuntos convergentes es convergente sin demostración adicional. Esa diferencia de forma es la que hace que un tipo convergente admita verificación mecanizada de manera natural, como muestra el trabajo de Gomes, Kleppmann, Mulligan y Beresford publicado en OOPSLA en 2017 con demostraciones comprobadas por máquina.
Hay un tercer eje de complejidad que no es de corrección sino de operación, y que decide más contrataciones de las que decide cualquier teorema. En OT, la parte difícil vive en el servidor, es un componente que el equipo despliega, observa y puede parchear en caliente el mismo día; si aparece un fallo de transformación, se corrige en un sitio y todos los clientes reciben el comportamiento nuevo al recargar. En un sistema convergente, la lógica de fusión vive en cada dispositivo, y un fallo en ella se corrige desplegando una versión nueva a instalaciones que quizá no se actualicen en meses y que mientras tanto seguirán generando datos con la semántica antigua. Eso obliga a versionar el formato desde el primer día y a diseñar las estructuras para que dos versiones del código puedan fusionar entre sí, que es una disciplina exigente y una fuente de trabajo permanente que las comparativas nunca contabilizan.
// En un sistema convergente el formato es un contrato entre versiones del codigo
const operacion = {
v: 3, // version del esquema de la operacion
tipo: "insertarTramo",
id: "r7.104",
desconocidas: {}, // campos futuros que esta version debe preservar
};
// Regla practica: nunca descartes campos que no entiendes al reenviar,
// o una version antigua borrara silenciosamente el trabajo de una nueva.
La honestidad exige añadir dos matices que suelen omitirse. El primero es que los algoritmos de secuencia convergente tienen sus propias sutilezas semánticas, y algunas se descubrieron tarde: el artículo sobre anomalías de entrelazado presentado por Kleppmann, Gomes, Mulligan y Beresford en el taller PaPoC de 2019 documenta que varios algoritmos publicados pueden mezclar párrafos escritos concurrentemente de una forma que ningún autor pretendía. Converger no es lo mismo que converger a algo razonable, y esa segunda propiedad no se sigue del álgebra. El segundo matiz es que la comparación sigue siendo objeto de discusión académica activa: el artículo de Sun, Sun, Ng y Cai publicado en 2020 en las actas de la conferencia CSCW examina las diferencias de corrección y complejidad entre ambas escuelas y defiende que buena parte de las ventajas atribuidas a una de ellas dependen de qué variantes se comparen.
Metadatos
OT guarda el documento y una historia podable. El CRDT guarda identidad y marcas, y la compresión de tramos ha recortado mucho esa distancia.
Complejidad
En OT es global y cuadrática en tipos de operación. En un CRDT es local a cada tipo, se compone y admite verificación mecanizada.
Topología
OT desplegado exige estrella con servidor que ordena. Un CRDT converge en cualquier grafo, incluido el intercambio esporádico entre pares.
La pregunta que decide
¿El servidor tiene que existir de todos modos? Si la respuesta es sí, OT no paga su peor factura. Si es no, la paga entera.
Topología: la factura que no se negocia
La tercera factura es la única que no admite ingeniería intermedia, y por eso es la que decide en un contexto local-first. Un CRDT converge bajo cualquier patrón de comunicación mientras cada actualización llegue eventualmente a todas partes: estrella, malla, intercambio ocasional entre dos dispositivos en la misma habitación, sincronización diferida a través de un disco que alguien lleva en el bolsillo. La convergencia no es una propiedad del despliegue sino del tipo de dato, y por eso sobrevive a cualquier despliegue.
Esa indiferencia a la topología tiene además una consecuencia de diseño que se aprecia poco desde fuera: permite añadir participantes que no son personas. Un servicio de copia de seguridad que solo fusiona y guarda, un índice de búsqueda que se suscribe a las actualizaciones, un dispositivo que sincroniza cada varios días, un proceso de importación masiva ejecutado sin conexión. Todos ellos son réplicas de pleno derecho y ninguno necesita permiso ni tratamiento especial, porque el contrato es el mismo para todos. En una arquitectura con servidor que ordena, cada uno de esos actores es una integración distinta contra una interfaz privilegiada.
// Cualquier participante es una replica mas: el contrato no distingue roles
const copiaDeSeguridad = crearReplica("respaldo-1");
const indice = crearReplica("busqueda-1");
const movil = crearReplica("telefono-de-ana");
sincronizar(movil, copiaDeSeguridad); // sin internet, en la misma red local
sincronizar(copiaDeSeguridad, indice); // horas despues, por otro camino
// El estado final es el mismo con independencia del orden y de la ruta
OT en su variante desplegada no. La lección tres estableció por qué: el servidor no es un componente de infraestructura sino parte del argumento de corrección, porque es él quien produce el orden que hace innecesaria la propiedad difícil. Dos dispositivos de la misma persona con red local perfecta y sin acceso a internet no pueden fusionar sus cambios en un sistema Jupiter, y eso no se arregla cambiando el transporte. La variante entre iguales de OT existe y evita ese problema, a costa de tener que demostrar precisamente lo que la lección dos mostró que no se puede demostrar con funciones de transformación clásicas sobre secuencias.
flowchart TD Q1[hay un servidor que va a existir de todas formas] --> SI[si] Q1 --> NO[no o no siempre] SI --> Q2[el documento es enorme y con historia muy larga] Q2 --> OT[OT con modelo Jupiter sigue siendo excelente] Q2 --> Q3[hace falta trabajar desconectado durante dias] Q3 --> CRDT1[conviene una estructura convergente] NO --> CRDT2[estructura convergente sin alternativa razonable] CRDT2 --> Q4[el volumen de historia se vuelve un problema] Q4 --> EG[recorrido del grafo de eventos como punto intermedio] style OT fill:#f9e2af,color:#11111b style CRDT1 fill:#a6e3a1,color:#11111b style CRDT2 fill:#a6e3a1,color:#11111b style EG fill:#cba6f7,color:#11111b
Por qué OT sigue vivo y dónde
Queda por señalar el límite que ninguna de las dos familias supera y que conviene no atribuirle a una sola: las invariantes globales. Que el saldo de una cuenta no baje de cero, que dos personas no reserven la misma butaca, que un identificador sea único en todo el sistema. Ninguna estructura convergente puede garantizarlas sin coordinación, porque garantizarlas es precisamente lo que la coordinación significa; y OT tampoco las garantiza por sí mismo, aunque su servidor, al existir, ofrece un sitio evidente donde comprobarlas. Si tu dominio tiene invariantes de ese tipo, la discusión de este nivel no las resuelve y hay que tratarlas aparte, normalmente aislando el subconjunto de datos que las necesita y aceptando que ese subconjunto sí requerirá acuerdo.
Con las tres facturas separadas, la persistencia de OT deja de ser un misterio y se vuelve una consecuencia aritmética. En un producto de suscripción con colaboración en tiempo real, el servidor va a existir de todas formas por autenticación, permisos, facturación y búsqueda, de modo que la peor factura de OT vale cero: no se está pagando una topología obligatoria, se está reutilizando una que el producto ya tenía. En ese cuadrante, la ventaja de guardar el documento en lugar de su historia es una ventaja neta, la matriz de transformación es un coste que se paga una vez con un equipo especializado, y la base instalada de implementaciones probadas durante quince años a escala enorme vale más que cualquier elegancia.
El inventario de cuadrantes donde OT sigue siendo la respuesta correcta es más largo de lo que sugiere el entusiasmo por la otra escuela, y conviene tenerlo escrito. Suites ofimáticas de escala masiva con documentos muy grandes, historias de años y colaboración esencialmente síncrona. Sistemas donde el contenido no puede residir íntegro en el cliente por volumen o por normativa, y donde por tanto la premisa de la réplica completa —que toda esta familia convergente da por buena— no se sostiene. Productos con esquemas estrictos validados por una autoridad. Y, de forma muy prosaica, cualquier equipo que ya tenga una implementación OT funcionando en producción: reescribir el núcleo de sincronización de un producto vivo es de las migraciones más caras que existen, y la mejora tiene que justificarse con requisitos concretos y no con propiedades atractivas.
Hay además dos ventajas cualitativas que sobreviven a toda la comparación. La primera es que OT conserva las operaciones originales, lo que hace natural expresar deshacer selectivo, atribución por autor y semánticas de intención sobre documentos estructurados. La segunda es que un servidor que ordena puede además validar: en un editor con esquema estricto, donde no todo documento sintácticamente posible es legal, tener una autoridad que rechaza o reajusta operaciones que romperían el esquema resuelve una clase de problemas que las estructuras convergentes, por construcción, no pueden resolver solas —la convergencia garantiza que todos vean lo mismo, no que lo que vean cumpla una invariante global—.
La dicotomía de este nivel es real históricamente pero no es exhaustiva. El trabajo Collaborative Text Editing with Eg-walker: Better, Faster, Smaller, de Joseph Gentle y Martin Kleppmann, presentado en la conferencia EuroSys de 2025, describe un enfoque de recorrido del grafo de eventos que ocupa deliberadamente la posición intermedia: guarda las operaciones originales tal como hace OT, en lugar de mantener una estructura con identidad persistente para todo el documento, y aun así converge sin ningún servidor central, replicando internamente solo los tramos del grafo que están genuinamente en concurrencia. El nivel 35 lo desarrolla entero. Lo que conviene retener ahora es que la frontera entre las dos escuelas no era una ley de la naturaleza sino la consecuencia de dos premisas que nadie había vuelto a cuestionar a la vez.
Llegados al final del nivel, conviene reordenar toda la comparación en torno al eje que de verdad la gobierna, porque no es ninguno de los tres que acabamos de medir. Los metadatos se optimizan, la complejidad se encapsula y la topología se negocia con el producto; son facturas reales pero son facturas de ingeniería. La diferencia que no se puede refactorizar es otra, y se hace visible cuando preguntas qué información conserva cada familia sobre lo que ocurrió. Un sistema OT con servidor conserva una historia: la secuencia que el servidor decidió, autoritativa, total, cómoda de auditar y podable en cuanto todo el mundo la ha confirmado. Un sistema convergente conserva el grafo parcial de lo que cada réplica supo: no hay una secuencia sino un orden parcial, con ramas que existieron a la vez y que siguen siendo recuperables mucho después. Fíjate en que esa diferencia es exactamente la que el nivel 22 estableció al distinguir un reloj físico de un vector de versiones, y en que no es una diferencia de eficiencia sino de expresividad: el primer sistema no es que guarde peor el orden parcial, es que su representación no puede expresarlo, igual que un orden total no puede expresar la incomparabilidad. De ahí se sigue la pregunta que conviene hacerse antes de elegir, y no se parece a las que suelen aparecer en las comparativas. No es cuántos bytes por carácter, ni cuántas operaciones por segundo, ni cuántas líneas de código. Es: ¿necesito poder responder, dentro de cinco años y sin el servidor delante, quién sabía qué cuando escribió esto? Si la respuesta es no —y para una enorme cantidad de productos legítimos es no— entonces la historia lineal del servidor es una representación más barata, más rápida y más fácil de operar, y elegir la otra por afinidad estética es cargar con metadatos que nunca vas a consultar. Si la respuesta es sí, ninguna optimización de OT te va a acercar, porque lo que falta no está comprimido: no está representado. Y aquí es donde este nivel se conecta con todo lo que viene después. Los quince niveles siguientes del track no van sobre estructuras convergentes porque sean el estado del arte ni porque sean bonitas, sino porque conservar el orden parcial es la única forma conocida de que dos copias de un documento puedan reconciliarse sin pedirle permiso a nadie, y esa capacidad es la definición operativa de local-first, no una de sus consecuencias. El trabajo sobre recorrido del grafo de eventos que acabamos de adelantar refuerza esta lectura en vez de matizarla: su aportación no consiste en fusionar mejor, sino en demostrar que se puede conservar el grafo parcial pagando en metadatos algo mucho más parecido a lo que paga OT. Es decir, atacar la factura sin ceder la expresividad. Ese es el patrón que conviene aprender a reconocer, porque es el que separa el progreso real de la moda: cuando aparezca la próxima técnica, la pregunta útil no será si es más rápida, sino qué premisa ha dejado de dar por buena.
- Mide el tamaño en reposo, en memoria y en red de una biblioteca convergente sobre un documento real de tu producto con su historia completa.
- Repite la medición aplicando compresión de tramos y compara el coste amortizado por carácter antes y después.
- Cuenta los tipos de operación que tu modelo necesitaría en OT, calcula el tamaño de la matriz y estima el trabajo de verificación asociado.
- Escribe los tres escenarios de topología de tu producto —servidor disponible, red local sin internet, dispositivo aislado durante días— y marca cuáles son requisitos y cuáles deseos.
- Determina si tu documento tiene invariantes globales que ninguna réplica puede verificar por su cuenta, y qué harías con ellas sin autoridad central.
- Escribe en un párrafo la respuesta a la pregunta del callout anterior para tu producto concreto, y usa esa respuesta y no las cifras para decidir.