¿Qué significa realmente 'offline-first' a nivel arquitectónico?
Offline-first no es un botón de reintentar pegado sobre la capa de red — es hacer que la base de datos local sea la fuente de verdad y tratar la red como un escritor más.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
¿Qué significa realmente 'offline-first' a nivel arquitectónico?
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Soporte offline vs. offline-first
La mayoría de las apps tienen algo de soporte offline: un spinner, un botón de reintentar, quizás una cola de peticiones que se vacía cuando vuelve la red. Eso sigue siendo una arquitectura network-first con un parche encima — la fuente de verdad es el servidor, y la app se degrada con gracia cuando no puede alcanzarlo. Offline-first es un diseño distinto: la base de datos local es la fuente de verdad para la UI, punto, y la red se convierte en una entrada más que eventualmente actualiza esa base de datos. La app nunca espera a la red para renderizar algo que el usuario pidió.
#La regla que lo hace funcionar
Cada lectura que hace la UI va al almacenamiento local, nunca directamente a la red. Cada escritura que hace el usuario cae primero en el almacenamiento local, de forma síncrona y optimista, y solo después se propaga al servidor mediante un motor de sincronización en segundo plano. Esta única regla es lo que hace que una app se sienta instantánea incluso en un tren atravesando túneles: la UI nunca está bloqueada esperando un round trip, porque nunca estuvo hablando con la red en primer lugar.
Nota que ambos caminos pasan por la base de datos local — la UI nunca está en ninguna flecha que toque la red directamente. Una lectura es: la red llena la BD, la BD alimenta a la UI. Una escritura es: la UI llena la BD, la BD alimenta a la red a través del outbox.
#Las piezas que realmente construyes
La base de datos local necesita contener más que datos del servidor — necesita una tabla outbox (o de "mutaciones pendientes") que registre cada escritura del usuario que aún no ha sido confirmada por el servidor, usualmente con una clave de idempotencia generada en el cliente para que una petición reintentada no se aplique dos veces en el servidor. El motor de sincronización — WorkManager en Android, BGTaskScheduler en iOS — vacía ese outbox cada vez que vuelve la conectividad, con backoff exponencial en caso de falla, y por separado hace polling o se suscribe para traer estado fresco del servidor y fusionarlo de vuelta.
La capa de UI necesita renderizar tres estados por cada dato, no dos: sincronizado, pendiente (escrito localmente, aún no confirmado) y fallido (el servidor rechazó la escritura — un conflicto, un error de validación). La mayoría de los bugs de offline-first que he visto en revisión no tienen nada que ver con el motor de sincronización; son una UI que solo conoce "cargado" y "cargando" y no tiene ningún lenguaje visual para "pendiente" o "en conflicto".
#Lo que sacrificas
Esta arquitectura te da una UI instantánea y acceso de lectura totalmente offline, pero cuesta: cada mutación ahora tiene dos ciclos de vida en vez de uno (aplicación local, confirmación remota), necesitas una estrategia de reconciliación para cuando los dos discrepan — que es su propia lección — y tu esquema local tiene que versionarse y migrar de forma independiente al del servidor, porque un usuario puede estar corriendo una versión vieja de la app contra un backend más nuevo durante semanas.