10 puntos por GN⁺ 2025-09-23 | 1 comentarios | Compartir por WhatsApp
  • Las apps local-first prometen respuesta rápida y privacidad básica por defecto, pero tienen la limitación de que implementar un soporte offline real es muy difícil.
  • La razón principal es la complejidad de la sincronización: cuando se modifican datos al mismo tiempo en varios dispositivos, el sistema debe converger exactamente al mismo estado.
  • Hay dos grandes retos técnicos: la incertidumbre del orden temporal y los conflictos.
  • Para resolver esto, es necesario aplicar diseños de sistemas distribuidos como Hybrid Logical Clocks (HLCs) y CRDTs.
  • Al aprovechar extensiones basadas en SQLite, se puede ofrecer una arquitectura de sincronización simple y confiable, utilizable en todas las plataformas.

La promesa y la realidad de las apps offline-first

  • Las apps offline-first prometen respuesta inmediata, privacidad básica por defecto y uso sin esperas de carga incluso en redes inestables.
  • En la práctica, la mayoría de las apps no implementan bien el soporte offline; la gran mayoría solo adopta un enfoque de guardar temporalmente los cambios en local y enviarlos después cuando vuelve la conexión.
  • Esta implementación es poco confiable y termina derivando en mensajes de advertencia como "es posible que los cambios no se guarden".

La dificultad fundamental de la sincronización

  • Al crear una app local-first, inevitablemente se termina construyendo un sistema distribuido.
  • Varios dispositivos pueden modificar los datos de forma independiente mientras están offline y, cuando vuelven a conectarse, deben converger con exactitud al mismo estado.
  • Para lograrlo, hay dos grandes desafíos:
    • Incertidumbre en el orden de los eventos
    • Conflictos sobre los mismos datos

1. Incertidumbre en el orden de los eventos

  • Los eventos ocurren en distintos momentos en varios dispositivos, y el estado puede cambiar según el orden.
    • Ejemplo: el dispositivo A establece x=3, el dispositivo B establece x=5 → tras hacer cambios por separado en offline, al sincronizar puede haber resultados distintos.
  • Las bases de datos centralizadas tradicionales lo resuelven con consistencia fuerte, pero eso requiere sincronización global y no encaja con un sistema local-first.
  • Al final, hace falta determinar el orden adecuado para cada evento incluso en un entorno dinámico y distribuido; se necesita una forma de ordenar sin un reloj central.

Introducción de Hybrid Logical Clocks (HLCs)

  • Hybrid Logical Clocks (HLCs) son un algoritmo simple pero efectivo que permite acordar en la práctica el orden de los eventos entre dispositivos.
  • HLC combina información de tiempo físico y un contador lógico.
  • Por ejemplo:
    • El dispositivo A registra un evento a las 10:00:00.100, y su HLC es (10:00:00.100, 0)
    • El dispositivo B, al recibir el mensaje, aunque su reloj vaya más lento, eleva su HLC a (10:00:00.100, 1)
    • Así, es posible fijar correctamente el orden de los eventos sin importar la diferencia entre los relojes físicos de ambos dispositivos.

2. El problema de los conflictos

  • Aplicar el orden correcto no es suficiente: si distintos dispositivos modifican de forma independiente los mismos datos, los conflictos son inevitables.
  • La mayoría de los sistemas exige que el desarrollador escriba manualmente el código de resolución de conflictos, lo que provoca riesgo de errores y carga de mantenimiento.

Uso de CRDTs

  • La mejor opción es aplicar Conflict-Free Replicated Data Types (CRDTs).
  • Los CRDTs garantizan que sin importar el orden de sincronización, o incluso si una operación se aplica duplicada, el estado final de cada dispositivo siempre será el mismo.
  • La estrategia CRDT más simple es Last-Write-Wins (LWW).
    • A cada actualización se le asigna una marca de tiempo.
    • Durante la sincronización, se elige el valor con la marca de tiempo más reciente.

Ventajas de SQLite

  • Para construir una app local-first, es indispensable contar con una base de datos local ligera y confiable, y SQLite es la mejor elección.
  • Si se implementa la sincronización mediante extensiones del framework basadas en SQLite, se obtienen ventajas como:
    • Aplicar mensajes es simple: consultar el valor actual → si la nueva marca de tiempo es más reciente, sobrescribir → si no, ignorar
    • Este método garantiza la convergencia del estado en todos los dispositivos sin depender del orden de sincronización

El significado de esta arquitectura

  • Esta estructura hace posible una sincronización simple y confiable:
    • Confiabilidad sin pérdida de datos incluso tras semanas en modo offline
    • Propiedad determinista de converger siempre al estado final
    • Se resuelve solo con una extensión ligera de SQLite y sin dependencias pesadas
    • Soporte para todas las plataformas principales: iOS, Android, macOS, Windows, Linux, WASM, etc.

Recomendaciones para desarrolladores

  • Conviene evitar enfoques que solo "simulan" soporte offline con una cola simple de requests.
  • Es necesario adoptar el concepto de eventual consistency y aprovechar tecnologías probadas de sistemas distribuidos como HLC y CRDT.
  • En lugar de frameworks grandes y complejos, es preferible buscar estructuras pequeñas y sin dependencias.
  • Como resultado, la app puede disfrutar de ventajas como inicio inmediato, uso offline y privacidad básica por defecto.

Referencia al open source SQLite-Sync

  • Si te interesa un motor offline-first multiplataforma, listo para usar en producción, puedes revisar la extensión open source SQLite-Sync

1 comentarios

 
GN⁺ 2025-09-23
Opiniones en Hacker News
  • Se habla de los CRDT (Conflict-Free Replicated Data Types) como si fueran la solución, pero en la práctica es realmente difícil crear un modelo CRDT que encaje tanto con las expectativas intuitivas del usuario como con una lógica de negocio consistente, y además convertir el modelo de datos en un conjunto de mensajes para luego reconstruir continuamente el estado real es un dolor de cabeza enorme
    • Existe una nueva iniciativa de estándar web llamada BRAID. Apunta a un estándar para sincronización del estado en la web, aplicando transformación operacional (OT) y tecnologías CRDT a HTTP para crear, en esencia, una web sincronizada más amigable tanto para humanos como para máquinas. Braid mejora el rendimiento de red y permite edición colaborativa nativa, P2P y desarrollo de webapps local-first. Enlaces relacionados: reunión de BRAID, discusión de Braid en HN, discusión sobre API RESTful, explicación de Braid HTTP
    • Se habla de los CRDT como si fueran una solución universal, pero en realidad la fusión automática no siempre es sencilla. Técnicamente, incluso un algoritmo de “último en escribir gana” puede considerarse un CRDT, pero respetar tanto la intención como las expectativas del usuario en fusiones complejas de texto es un problema casi imposible. Incluso hay casos en los que intentar fusionar con CRDT es, de hecho, el enfoque equivocado. Por ejemplo, si dos personas reservan al mismo tiempo la misma sala de reuniones, el conflicto no debería resolverlo el algoritmo, sino que el usuario debería detectarlo y resolverlo directamente
    • Coincido en que es un terreno difícil para quien no se atreve a lanzarse. También hay una alternativa “sin CRDT” para quienes no quieran complicarse; se puede ver aquí
    • Nuestro equipo, al crear apps local-first, usa un método que básicamente ignora los conflictos. Gana el último cambio. La mayoría de los conflictos son triviales (o se pueden resolver fácilmente con algo como un log de auditoría), o directamente no se pueden resolver de forma automática. Por ejemplo, en un rastreador de tareas con soporte offline, si dos personas inician la misma tarea al mismo tiempo, eso debe resolverse aparte como parte del proceso de negocio
  • Antes, casi todo el software era local-first, y eso era lo normal. Pero hoy el mundo funciona totalmente en torno al control y la optimización de ganancias, y el resultado es una estructura en la que la gente sale perjudicada con más frecuencia. Aunque haya descontento, casi no existen sustitutos reales
    • En la época en que hacíamos productos on-premise y autoalojados, la mayor queja de los clientes era que no había opción en la nube. La mayoría de las empresas no quiere autoalojar y prefiere pagar una suscripción mensual y dejarlo en manos de otros. Creo que HN subestima cuánto se demanda realmente el cloud
    • La idea de que “si la gente quiere servicios que la perjudiquen menos, se puede ganar dinero con eso” no se sostiene económicamente. El problema es que la gente en la práctica tolera cierto grado de perjuicio. Tal vez sería distinto con más educación o conciencia del riesgo, pero eso me parece un problema dificilísimo de resolver
    • Como alternativa, se puede pensar en FOSS (software de código abierto)
  • Ojalá las apps no dependieran de que todo el contenido esté únicamente online. El GPS de Tesla ni siquiera guarda en caché los tiles que ya descargó, así que offline no aparece nada en el mapa. Apps como Peacock y Kanopy tampoco dejan en el dispositivo ni la lista de medios ni los objetos renderizados. El dispositivo ya tiene el 95% del contenido, así que ojalá se aprovechara de forma activa. Basta con marcar la UI como dirty mientras se espera el guardado asíncrono. Sin exigir grandes cambios de diseño para apps offline, con mejores hábitos se pueden resolver fácilmente la mayoría de estos problemas
    • Muchos problemas se resuelven usando correctamente Cache-Control en las respuestas de la API y respetándolo en la capa de red. Así, aunque se cambie la vida útil del caché desde el servidor, se aplica de inmediato sin necesidad de actualizar la app
    • Google Maps permite descargar manualmente áreas para mapas offline y también guardar varias zonas a la vez. Me ha funcionado bien al visitar parques nacionales
    • Sobre la idea de que “no hace falta cambiar el diseño de la app”, creo que muchas empresas en realidad buscan recolectar más datos. Por ejemplo, Apple también ofrecía mapas offline, pero hacía expirar deliberadamente los datos para mantener al usuario dependiente de su ecosistema. Sospecho que los tiles de mapas de Tesla (o Google) también tienen algún motivo oculto
  • Muchas veces, al centrarse en temas “políticamente candentes” como que una app sea local-first o distribuida, se termina perdiendo de vista el valor central que la gente realmente quiere
    • Me cambié a Immich pensando que iba a sacrificar mucho por el self-hosting, pero me sorprendió que sea muchísimo mejor que Apple o Google. Es uno de esos productos rarísimos, casi como un unicornio
  • Creo que la razón principal por la que las apps local-first no se vuelven populares es económica. Los modelos SaaS o basados en anuncios están firmemente establecidos, mientras que las apps local-first son notablemente menos rentables. A quienes prefieren este modelo les importan características como soberanía de datos, cifrado de extremo a extremo y uso offline, que chocan con los modelos tradicionales de monetización. Al final, no queda más que depender de la pasión de la comunidad open source
    • Hoy parece que solo hay dos opciones: pagar con “dinero + datos” o “ver anuncios”; el modelo de pagar solo con efectivo real y mantener protegidos los datos prácticamente queda excluido
    • Yo también estoy creando una app local-first llamada Relay, que añade colaboración estilo Google Docs a Obsidian. Creo que su modelo de negocio es particular. El servicio se divide en una “capa global de identidad” y un “Relay Server” (open source / self-hosted), de modo que el usuario mantiene control total sobre el contenido de sus documentos. Ofrece SSO simple y gestión de permisos, y está generando interés especialmente entre empresas del ámbito de AI y AI Safety o compañías donde el compliance es clave. El enlace es Relay.md
    • Algo que veo mucho a mi alrededor es que, cuando al comprar solo ofrecen suscripción, el consumidor termina no comprando nada. Uno quiere comprar ahora y usar después, pero las restricciones (periodo de descuento, aumento de precio al volver más tarde, etc.) hacen que se pierdan las ganas de comprar por completo. No creo que ese sea el modelo de negocio óptimo
    • No creo que el problema sea la estructura de datos replicada. Incluso juegos para un solo jugador, que son totalmente local-first, muchas veces exigen conexión a internet por culpa del launcher
    • Las apps local-first también tienen un problema serio de complejidad. Deben funcionar en todo tipo de dispositivos y entornos, mientras que las apps cloud-first solo tienen que correr en un único entorno del lado del servidor, así que son relativamente más fáciles y más baratas de mantener
  • Aunque hoy parezca que el software de escritorio y móvil es una excepción rara, sigue siendo una forma muy común de distribuir software. En cambio, si intentas implementar capacidades local-first en el navegador, terminas cargando además con las desventajas propias del navegador, como los problemas de integración con el sistema anfitrión
  • Tal vez se me escape algo, pero en general me parece que las apps “local-first” sí son lo normal. La mayoría de los usuarios también usa muchas apps basadas en funcionamiento offline. Si en realidad se quiere decir “web apps local-first”, entonces esa expresión tendría más sentido. De hecho, “web app local-first” es en sí un concepto contradictorio
    • Me gustaría devolver la pregunta: ¿la mayoría de las apps realmente son local-first en el sentido de que se usan pagando directamente por ellas? Fuera de los videojuegos, ya casi no quedan empresas así, e incluso los juegos single-player hoy suelen exigir internet con la excusa del DRM, antitrampas, actualizaciones, etc.
    • Aquí, “local-first” significa una app que toma los datos locales como base desde el principio, en lugar de depender del almacenamiento en la nube, y luego ofrece sincronización con la nube
  • Incluso las apps offline-first no se libran de quedarse girando con un spinner cuando la red está inestable. Por ejemplo, Google Docs se queda intentando verificar si el documento está actualizado, y solo abre al instante si uno fuerza el corte con Airplane Mode. Spotify también se detiene intentando obtener información adicional online incluso para playlists ya guardadas. Al final, una conexión inestable es el mayor dolor de cabeza en el desarrollo de apps offline, porque las apps siempre intentan acceder хотя sea una vez más a los datos en la nube
  • La solución del artículo también queda atrapada dentro de una oferta cloud cerrada. Como Firebase, que en sí no está mal, pero es decepcionante que eso no se indique claramente y que quede escondido detrás de expresiones como “solo una extensión de sqlite”, cuando en realidad solo admite una nube comercial. Proveedores como Powersync o ElectricSQL al menos son transparentes sobre ese hecho, y Powersync además permite self-hosting
    • No me queda del todo claro si el concepto de local-first puede aplicarse a herramientas para desarrolladores. Da la impresión de que habría que evaluar si herramientas tipo SQLite-sync permiten construir software basado en un modelo de almacenamiento local. ElectricSQL puede self-hostearse, y quizá también deba seguir actualizando mi lista de herramientas “sqlite sync”. Enlaces relacionados: artículo original sobre local-first, SQLSync, SQLiteSync, SQLite-Sync
  • Creo que necesitamos más apps exclusivamente locales y autoalojadas. O también estructuras federadas. Siento que la infraestructura de red había sido un obstáculo hasta ahora, pero con la aparición de soluciones como Tailscale este tipo de apps se volverá mucho más fácil
    • Estoy desarrollando software de presentaciones, y tiene que funcionar perfectamente en local, pero al mismo tiempo debe poder accederse desde cualquier lugar. Satisfacer ambas cosas a la vez es más difícil de lo que parece. Aun así, conforme avanza la tecnología, implementar P2P mediante conexiones directas o WebRTC se está volviendo más sencillo. Integrarlo en un producto real y probarlo sigue siendo un reto. Pero creo que en adelante veremos cada vez más software que sea local-first y además tenga muy buenas capacidades de red. Es open source. Más detalles en mi perfil
    • Yo también he estado explorando esto últimamente y me parece muy interesante. Se puede leer más aquí. Está siendo bastante divertido construir apps de una forma nueva