Local-first frente a offline-first
La diferencia entre local-first y offline-first no está en si la app funciona sin red, sino en dónde vive la fuente de verdad: una aplicación puede ser impecablemente offline-first y seguir siendo, en su núcleo, una aplicación del servidor.
Si la lección anterior te dejó una intuición, que sea esta: offline-first describe un comportamiento y local-first describe una constitución. Ahora toca ponerlas una junto a la otra y aislar con precisión quirúrgica qué las separa, porque la respuesta intuitiva —que local-first es offline-first llevado más lejos, una especie de versión premium— es falsa y además es la fuente de la mayoría de los errores de diseño en este campo. No están en la misma escala. No se trata de cuánto aguanta la aplicación sin red, ni de cuántos datos guarda, ni de lo rápido que arranca. La diferencia cabe en una sola pregunta, y esa pregunta no menciona la conectividad ni una sola vez: cuando la copia que vive en tu dispositivo y la copia que vive en el servidor no coinciden, ¿cuál de las dos es la verdad y cuál es la que tiene que ceder?
- Formular la distinción en términos de sede de la fuente de verdad y no de tolerancia a la desconexión.
- Aplicar el test del servidor apagado como discriminador operativo entre ambas categorías.
- Entender por qué los dos conceptos son ejes ortogonales que admiten las cuatro combinaciones.
- Reconocer qué obligaciones nuevas aparecen en el momento en que la verdad se muda al cliente.
- Saber por qué la disponibilidad es frágil y la propiedad es persistente, y qué implica esa asimetría.
La sede de la verdad
Empecemos por el caso que más gente clasifica mal. Imagina un gestor de tareas que guarda una réplica completa de tus proyectos en el dispositivo, arranca sin red en menos de cien milisegundos, acepta todas tus ediciones estando desconectado y las sube cuando vuelves. Por el criterio de la lección anterior, es offline-first sin discusión. Ahora añade un detalle de su implementación: al reconectar, el servidor vuelve a ejecutar cada una de tus ediciones contra su propio estado, y si alguna no le cuadra —porque otro colaborador tocó lo mismo, porque tus permisos cambiaron, porque una regla de negocio lo prohíbe— la rechaza, y tu cliente la deshace. Esa aplicación no es local-first, y no lo es aunque no hayas visto nunca una rueda de carga.
Fíjate en que ninguno de los rasgos que enumeré primero es irrelevante: la réplica completa, el arranque instantáneo y la escritura desconectada son logros de ingeniería considerables y mejoran la vida del usuario todos los días. Lo que ocurre es que ninguno de ellos habla de autoridad, y por tanto ninguno puede sostener por sí solo la promesa que local-first hace. Es la diferencia entre tener las llaves de una casa y ser su propietario: el juego de llaves resuelve el noventa y nueve por ciento de los días y no dice nada sobre el uno por ciento en que aparece el dueño real.
La razón es que su copia local nunca tuvo autoridad. Tenía algo distinto y más débil: capacidad de anticipación. Podía adelantar lo que probablemente iba a ocurrir, con una tasa de acierto altísima, pero la palabra final estaba en otro sitio. Y donde está la palabra final está la fuente de verdad. La réplica local era, en términos estrictos, una caché de escritura diferida muy bien construida: rápida, duradera, cómoda, y sin ningún derecho.
Local-first invierte esa relación. La copia que vive en tu dispositivo deja de ser una proyección de un estado remoto y pasa a ser el estado, sin adjetivos. Escribir en ella es un hecho consumado en el instante en que ocurre; no hay una instancia superior que pueda anularlo después. Lo que la red hace en esta arquitectura no es autorizar sino replicar: llevar tu verdad a tus otros dispositivos y a los de tus colaboradores, y traerte las suyas. Degradas la red de tribunal a servicio de mensajería, y ese cambio de papel es la reforma constitucional entera.
Vale la pena insistir en que la palabra clave es primaria y no única. Local-first no dice que no haya servidor ni que no haya copias remotas; sería una lectura ingenua que ningún sistema serio sostiene, porque los usuarios pierden dispositivos y necesitan colaborar. Dice que la copia del usuario tiene la condición de original y las demás la de derivadas. Es la misma distinción que existe entre un manuscrito y sus fotocopias: puede haber cien fotocopias en cien archivos, y ninguna de ellas adquiere por acumulación la autoridad del original.
Del mismo modo, tampoco exige que todos los datos del sistema sean soberanos. Un producto puede declarar que el contenido creado por el usuario es primario en su dispositivo mientras la lista de suscripciones, los permisos de un equipo o el registro de facturación siguen siendo del servidor sin discusión. Esa mezcla no es una traición al principio, es la forma en que se aplica a un producto real, y su condición de honestidad es que el reparto esté escrito y sea consultable en lugar de resolverse por omisión.
flowchart TB subgraph OF[offline first] C1[cliente con cache duradera] -->|propone| S1[servidor autoritativo] S1 -->|acepta o rechaza| C1 end subgraph LF[local first] C2[replica primaria del usuario] -->|replica| R[relevo o par] R -->|replica| C2 end style S1 fill:#f38ba8,color:#11111b style C2 fill:#94e2d5,color:#11111b
Fíjate en los verbos de las flechas, que es donde está toda la información. Arriba el cliente propone y el servidor dispone; el vocabulario es el de una solicitud. Abajo ambos extremos replican; el vocabulario es el de un intercambio entre iguales. Los dos dibujos tienen dos nodos y dos flechas, y describen sistemas con propiedades legales opuestas.
El test del servidor apagado
Como la distinción es de autoridad y la autoridad no se ve, hace falta un experimento que la revele. El mejor que conozco es un experimento mental brutal: imagina que la empresa que opera el servidor cierra esta noche, apaga la infraestructura y nadie recupera nunca esos discos. Mañana por la mañana, ¿qué te queda?
Si la respuesta es que te queda una aplicación que abre, muestra tus datos, te deja seguir trabajando y podría sincronizar con otro dispositivo tuyo si montaras un relevo alternativo, tienes una arquitectura local-first. Si la respuesta es que te quedan unos megabytes en un almacén del navegador que solo el código de esa empresa sabía interpretar, y una interfaz que ya no se sirve desde ningún sitio, tienes una aplicación offline-first cuyos datos eran del servidor todo el tiempo. El experimento es duro a propósito: es la única forma de separar la comodidad de la propiedad, porque en el día a día ambas se sienten idénticas.
El test tiene una virtud metodológica que conviene explicitar: no depende de la buena voluntad del proveedor ni de sus promesas contractuales. Un compromiso de exportar tus datos si el servicio cierra es una obligación que solo vale mientras exista alguien capaz de cumplirla, y la insolvencia es precisamente el escenario en que nadie cumple nada. La pregunta del apagón evita esa dependencia porque solo admite una respuesta técnica: o los bytes están en tu dispositivo en un formato interpretable o no lo están. Es una comprobación sobre la física del sistema, no sobre su gobernanza.
Conviene además distinguir dos grados de superviviencia que suelen mezclarse. Un sistema puede garantizar que tus datos sobreviven como archivo legible —los tienes, los puedes abrir con otra herramienta— sin garantizar que la aplicación siga siendo operativa, porque su código se servía desde un dominio que ya no responde. Ese grado intermedio es mucho más frecuente de lo que se admite y no es despreciable: recuperar el contenido es casi siempre lo que importa. Pero conviene nombrarlo como lo que es, supervivencia de los datos y no del sistema, para no prometer continuidad de servicio donde solo hay continuidad de archivo.
El apagón es el titular, pero el diagnóstico fino sale de tres preguntas subsidiarias. Primera, la de integridad: ¿está en el dispositivo el conjunto completo de tus datos o solo el subconjunto que has consultado últimamente? Segunda, la de legibilidad: ¿el formato en disco está documentado o al menos es autodescriptivo, o es una serialización opaca al servicio de un motor concreto? Tercera, la de exportabilidad: ¿existe una salida a un formato que otro programa entienda, y funciona sin llamar al servidor? Un sistema que responde bien a las tres es local-first en el sentido fuerte. Uno que responde bien solo a la primera tiene una réplica completa y rehén.
Existe una versión más suave y muy útil del mismo test para productos que aún no han decidido nada: el test del proveedor hostil. No supongas que la empresa cierra, supón que sigue operando y decide multiplicar el precio por cinco, restringir la exportación al plan más caro o cambiar los términos de uso de tus datos. ¿Qué recurso te queda? Si la respuesta es negociar o irte con las manos vacías, la relación es de acceso y no de propiedad. Este test es más suave porque el escenario es mucho más probable que la insolvencia, y en la práctica discrimina igual de bien.
Observa que ninguna de esas preguntas menciona la latencia, y eso no es casual. La inmediatez es el ideal más barato de los siete y el único que se puede comprar con una caché; por eso es el que se anuncia. La longevidad, en cambio, no se puede fingir: o el formato sobrevive al proveedor o no sobrevive, y no hay optimización que lo simule. Cuando quieras saber si alguien ha hecho el trabajo, pregunta por lo que no se puede falsificar.
Ortogonales, no una escala
De lo anterior se sigue algo que conviene ver dibujado: no son dos puntos de una recta sino dos ejes de un plano, y el plano tiene cuatro cuadrantes, los cuatro poblados.
Ni lo uno ni lo otro
La aplicación web clásica de formulario y recarga. La verdad está en el servidor y sin red no hay nada. Sigue siendo la arquitectura correcta para una enorme cantidad de software, y decirlo en voz alta es parte de la honestidad de esta taxonomía.
Offline-first y del servidor
El cuadrante más poblado y el peor etiquetado. Réplica local generosa, arranque sin red, escritura encolada, y un servidor que conserva íntegro el derecho de veto. Es una arquitectura excelente para la inmensa mayoría de los productos colaborativos.
Local-first pero no offline
Suena a contradicción y no lo es. Sistemas cuya réplica es genuinamente primaria pero que ponen una verificación de sesión o una descarga de configuración en el camino crítico de arranque. La soberanía está diseñada; la disponibilidad se rompió por descuido.
Local-first y offline-first
El objetivo del manifiesto y el más caro de los cuatro. Exige a la vez que la copia local sea autoritativa, que el formato sobreviva al proveedor y que el arranque no dependa de nadie. Cada una de esas tres exigencias se paga por separado.
El cuadrante que más gente cree imposible es el tercero, y merece un momento de atención porque revela que la disponibilidad es frágil de una forma en que la propiedad no lo es. Basta un requisito de arranque mal colocado —una comprobación de licencia, una carga de traducciones desde la red, una redirección a un servicio de identidad— para que un sistema soberano se vuelva inutilizable en un avión. La propiedad es una decisión de arquitectura que persiste; la disponibilidad es una propiedad emergente que cualquier commit puede destruir sin que nadie lo note hasta que un usuario lo sufre.
Esa asimetría tiene una consecuencia práctica en cómo se protege cada una. La propiedad se protege con decisiones de diseño tomadas una vez y difíciles de revertir: un formato documentado, una clave que gestiona el usuario, un modelo en el que las escrituras no se revocan. La disponibilidad se protege con vigilancia continua: pruebas automáticas que arrancan la aplicación sin red en cada despliegue, presupuestos que fallan la construcción si aparece una petición nueva en el camino crítico, revisiones que preguntan por el comportamiento desconectado. Confundir un tipo de garantía con el otro lleva a equipos a auditar la propiedad cada semana, que no hace falta, y a no auditar nunca la disponibilidad, que se degrada sola.
Como este nivel dedica mucha energía a desmontar etiquetas, conviene decir con claridad que el cuadrante más poblado es también el más razonable para la mayoría del software colaborativo que existe. Un producto con permisos por rol, reglas de negocio que alguien debe hacer cumplir y clientes que esperan que el proveedor responda por la integridad del dato tiene excelentes motivos para conservar un árbitro central. Lo que este nivel critica no es esa elección sino la costumbre de tomarla y describirla con el vocabulario de la otra. Elegir bien y nombrarlo mal es un problema de comunicación; elegir mal por perseguir un nombre es un problema de arquitectura, y de los caros.
Lo que cambia cuando la verdad se muda
Mover la sede de la verdad al cliente no es gratis, y esta lección sería propaganda si terminara sin decir la factura. Cambian al menos cuatro cosas, y ninguna es menor.
| Dimensión | Con autoridad en el servidor | Con autoridad en el cliente |
|---|---|---|
| Invariantes globales | Garantizables por serialización | No exigibles sin reintroducir coordinación |
| Conflictos | Excepción que se resuelve rechazando | Régimen normal que exige regla de fusión |
| Permisos | Se aplican filtrando en el emisor | Se aplican cifrando, y revocar cuesta |
| Esquema | Migración coordinada y con ventana | Compatibilidad en ambos sentidos, sin ventana |
Cada fila de esa tabla es un capítulo entero de este track, y ninguna se puede saltar eligiendo bien la biblioteca. Conviene leerla no como una lista de dificultades sino como el precio explícito de una propiedad concreta: la irrevocabilidad de la escritura del usuario. Si esa propiedad no es esencial para tu producto, pagarla es un desperdicio; si lo es, no hay forma de obtenerla sin pasar por las cuatro filas.
Cambia lo que puedes prometer. Un servidor autoritativo puede garantizar invariantes globales —un nombre único, un saldo que no baja de cero, una plaza reservada una sola vez— porque tiene el privilegio de ver todas las escrituras y serializarlas. Cuando la autoridad se reparte entre réplicas que escriben sin coordinarse, esa clase de garantía se vuelve imposible en el caso general, y no por falta de ingenio: es un límite conocido. Se puede recuperar caso a caso reintroduciendo coordinación, pero entonces has vuelto a tener un árbitro y conviene admitirlo.
Cambia el estatus del conflicto. En una arquitectura de servidor autoritativo el conflicto es una excepción que alguien resuelve rechazando; en una local-first es el régimen normal de funcionamiento, porque todas las réplicas escriben legítimamente a la vez. Eso obliga a tener una respuesta explícita y siempre presente sobre cómo dos historias divergentes vuelven a ser una, y esa respuesta es un compromiso de por vida: cambiarla más tarde significa reinterpretar datos que ya existen en dispositivos ajenos.
Ese cambio de estatus tiene una consecuencia organizativa que sorprende a los equipos la primera vez. La regla de fusión deja de ser un detalle de implementación que un desarrollador decide en una tarde y pasa a ser una decisión de producto con consecuencias visibles: determina qué ve el usuario cuando dos personas trabajan a la vez, y por tanto qué considera correcto. Escribirla exige que alguien de producto y alguien de ingeniería se sienten a acordar qué significa fusionar en ese dominio, y esa conversación no se puede delegar en la biblioteca que se elija.
Cambia el control de acceso. Si la copia autoritativa está en el dispositivo, el servidor ya no puede filtrar lo que puedes leer sencillamente no enviándotelo, porque ya lo tienes. Los permisos dejan de ser una decisión del emisor y se convierten en un problema criptográfico: quien no debe leer algo no debe poder descifrarlo. El corolario incómodo es que revocar un permiso deja de ser una operación instantánea sobre una tabla y pasa a exigir rotación de claves y redistribución, con la certeza de que lo ya descifrado por alguien no vuelve a ser secreto.
Y cambia la migración del esquema, que pasa de ser una operación coordinada sobre una base que controlas a un ejercicio de compatibilidad en las dos direcciones contra dispositivos que llevan meses apagados. Un cliente en una versión antigua debe poder leer datos escritos por uno nuevo sin corromperlos, y un cliente nuevo debe poder leer los del antiguo sin perder información; ambas exigencias a la vez y sin ventana de mantenimiento, porque no hay nadie que pueda declararla. Es el problema peor documentado del campo y el que más proyectos hunde en su segundo año.
flowchart LR P[promesa que quieres hacer] --> Q[requiere ver todas las escrituras] Q -->|si| ARB[necesitas un arbitro central] Q -->|no| LOC[puede vivir en la replica del usuario] ARB --> C1[coste: la escritura local no es final] LOC --> C2[coste: conflictos permisos y esquema] style ARB fill:#f38ba8,color:#11111b style LOC fill:#94e2d5,color:#11111b
El diagrama resume el criterio operativo que este nivel intenta instalar: no empieces por la arquitectura, empieza por la promesa. Si la promesa que tu producto necesita hacer exige observar todas las escrituras a la vez, ya has elegido, y la elección trae consigo la lista completa de sus consecuencias. Si no lo exige, tienes la opción de mudar la verdad al cliente, y entonces la pregunta pasa a ser si estás dispuesto a pagar las cuatro facturas del apartado anterior. En ninguno de los dos caminos hay una respuesta correcta en abstracto; hay una respuesta correcta para un dominio concreto y una promesa concreta.
El error de encuadre que esta lección desmonta es tratar local-first como el extremo superior de una escala de tolerancia a la desconexión, como si bastara con cachear más agresivamente hasta cruzar una frontera. No hay tal frontera, porque no hay tal escala: son dimensiones distintas de un sistema y responden a preguntas distintas. La disponibilidad pregunta si el sistema acepta operaciones bajo partición, y es una decisión de la capa de entrega que se puede añadir, quitar o graduar sin tocar el modelo de datos. La autoridad pregunta qué ocurre con esas operaciones cuando la partición se cura, y es una decisión constitucional que determina el conjunto entero de invariantes que el sistema puede garantizar, la naturaleza de sus conflictos, la forma de su control de acceso y su estrategia de evolución del esquema. Por eso una aplicación puede ser impecablemente offline-first y seguir siendo del servidor hasta la médula: ha resuelto el problema de seguir funcionando bajo partición sin tocar el de quién manda al reunificarse, que es un problema de otro orden. Y por eso el camino de una a otra no es una optimización incremental sino una migración: no consiste en cachear mejor, sino en decidir que la réplica del usuario es primaria y aceptar las cuatro facturas —invariantes que ya no puedes prometer, conflictos como régimen normal, permisos por criptografía y esquemas que evolucionan sin coordinación— que esa decisión trae consigo. Quien entiende esto deja de preguntar cuánto aguanta una aplicación sin red y empieza a preguntar quién gana cuando dos copias discrepan, que es la única pregunta cuya respuesta predice todo lo demás.
- Elige tres aplicaciones que uses y que guarden datos: una de notas, una de tareas y una de comunicación. Para cada una, aplica el test del servidor apagado y escribe la respuesta en una frase.
- Coloca las tres en el plano de dos ejes: disponibilidad sin red en uno, sede de la verdad en el otro. Comprueba si alguna cae en el tercer cuadrante, el soberano que no arranca sin red.
- Busca en cada una la función de exportar. Ejecútala sin red y observa si funciona. Una exportación que necesita servidor es una confesión sobre dónde vive el formato.
- Para la que hayas clasificado como más cercana a local-first, enumera cuál de las cuatro facturas del último apartado paga: invariantes, conflictos, permisos o migración. Si no paga ninguna, revisa tu clasificación.