Saltar al contenido
Blog
Decidir y comprar software a medida

Qué cambia en un sistema cuando la app tiene que funcionar sin señal

Pedro CunhaPublicado el actualizado el 14 min de lectura

En resumen

Offline-first no es una funcionalidad de la aplicación: es una decisión que cambia la base de datos, el servidor y el alcance del producto — sobre todo, lo que no va al dispositivo. Y una app que promete offline y se traba es peor que una app honestamente online: la diferencia entre las dos está en detalles que casi nunca aparecen en la propuesta.

Qué es offline-first, y por qué no es caché#

La caché guarda la respuesta de una petición que ya ocurrió, para no repetirla. Sirve para acelerar la lectura y desaparece cuando el asunto es escritura: lo que el usuario crea sin señal no tiene dónde vivir.

Offline-first es otra cosa. La aplicación tiene una base de datos propia en el dispositivo, y es de ahí que lee la pantalla — lista, búsqueda, mapa, formulario. El servidor entra después, en segundo plano. La red deja de ser condición para que el trabajo ocurra.

La prueba lleva diez segundos: en modo avión, intentá crear algo. Una app con caché falla al guardar; una app offline-first da el alta, y el registro sigue ahí después de cerrar y volver a abrir.

La formulación más conocida de esta idea es el ensayo "Local-first software: you own your data, in spite of the cloud", publicado por el laboratorio Ink & Switch en 2019, con Martin Kleppmann entre los autores. De los siete ideales que enumera, el más relevante para el software corporativo es el más simple: la operación responde sin depender de una ida y vuelta a la red.

Cuándo vale offline-first — y cuándo es dinero tirado#

El criterio no es el rubro de la empresa. Es dónde ocurre el trabajo.

Un vendedor externo que atiende el interior de tres provincias trabaja donde la señal es una hipótesis, no un hecho. Un operario que hace checklist de equipos en obra, ídem. Un alumno que registra su entrenamiento en el gimnasio suele estar en el subsuelo. En esos casos, el momento en que se usa el sistema es justamente el momento en que la red no está. Y vale al revés: si la persona usa el sistema sentada, con Wi-Fi, offline-first es complejidad permanente a cambio de un problema que no tiene.

La segunda pregunta, cuando la primera da "sí", es qué necesita funcionar sin red. Solo consultar es un problema; registrar es otro, bastante mayor, porque exige una cola de salida y todo lo que viene con ella.

DecisiónQué imponeCuándo vale
Base local en el dispositivoespacio y memoria en el aparato; recorte explícito de qué datos bajanel trabajo ocurre lejos de una red confiable
Cola de escritura (envío posterior)orden entre registros, reintento en caso de falla y política para escritura rechazadala persona registra en campo, no solo consulta
Identificador generado en el dispositivoel servidor deja de ser quien bautiza el registrocualquier creación offline
Sincronización visible en la interfazpantallas y textos que la mayoría de las apps no tienesiempre — es lo que evita que el usuario crea que se trabó

Ninguna de esas líneas es opcional una vez elegida la primera. Por eso offline-first es una decisión de alcance, y no un ajuste fino al final del proyecto.

Por qué una app offline mala es peor que una app online honesta#

El sistema que Reticar Motores usaba antes del nuestro ya tenía comportamiento offline — y era exactamente el origen del dolor: la sincronización se disparaba en cada apertura y bloqueaba la aplicación entera mientras corría, empeoraba con conexión lenta o inestable, y el usuario no tenía cómo saber qué estaba pasando ni si lo que registró había subido.

El efecto en un equipo es previsible y caro: la persona deja de confiar en la aplicación y vuelve a anotar en papel para cargar después. Una app honestamente online, que dice "sin internet" y no finge, genera menos retrabajo que una app que promete autonomía y entrega congelamiento.

La diferencia entre las dos no es conceptual — es de granularidad, y son cuatro decisiones de implementación:

  • Descargar en páginas pequeñas. En la app de Reticar, cada página de descarga trae 100 registros. Nuestro proyecto base usa páginas mucho mayores, y para una base grande eso significa retener la interfaz demasiado tiempo.
  • Aplicar en lotes. Cuando la página es grande, los registros se graban en la base local en lotes de 40, y no de una sola vez.
  • Devolver la pantalla al usuario entre lotes. Entre un lote y otro, la aplicación devuelve el procesamiento a la interfaz para que atienda gestos y animación. Esa es la línea que separa "sincronizando en segundo plano" de "se trabó".
  • Mostrar qué está pasando, con nombre. La pantalla de sincronización dice la fase (enviando o descargando) y la colección en lenguaje claro — "Descargando clientes", "Descargando órdenes de servicio". Quien espera sabiendo qué espera no cree que la app se murió.

El resultado de esa suma, en Reticar: la primera sincronización — la más pesada, porque trae la carga inicial entera — lleva, en promedio, menos de 10 segundos para un vendedor típico, en el dispositivo Android del propio cliente y en red móvil. Las siguientes son bastante más rápidas, porque solo traen lo que cambió.

Qué cambia dentro de la aplicación#

Tres cambios estructurales, y ninguno es visual.

La pantalla pasa a leer de la base local. La lista no llama a la API: la interfaz observa la base del dispositivo y se actualiza sola cuando cambia — porque el usuario creó algo o porque la sincronización trajo novedades. Es lo que hace que la búsqueda sobre miles de registros sea instantánea, con red o sin ella.

La escritura se vuelve dos etapas. El registro se graba en la base local y se encola; la cola sube cuando hay red. Para el usuario, el alta terminó en el instante en que guardó.

El registro nace con identidad propia, generada en el dispositivo antes de cualquier contacto con el servidor. Sin eso, nada creado sin conexión podría ser referenciado por otro registro hasta que la app lograra preguntar "¿qué número le diste a esto?".

Hay una decisión nuestra con consecuencia directa en el alcance. Usamos RxDB como capa de datos reactiva, y su almacenamiento persistente oficial para SQLite es un plugin comercial — parte de las licencias Premium, con versión de prueba limitada a 500 documentos y sin índices, lo que no sirve para una base de miles de registros. Nuestra salida fue correr RxDB en memoria y mantener, por nuestra cuenta, un espejo en SQLite en el dispositivo.

La consecuencia de eso es la parte que le interesa a quien contrata: la base sincronizada ocupa memoria del dispositivo. Decidir qué baja al aparato deja de ser solo una cuestión de tiempo de descarga y se vuelve presupuesto de memoria. Es lo que vuelve obligatoria, y no recomendable, la sección siguiente.

Qué cambia en el servidor#

Esta es la parte que suele sorprender: la mayor parte del trabajo de offline-first no está en la aplicación.

Una API tradicional responde "dame la lista de clientes". Una aplicación offline pregunta otra cosa: "¿qué cambió desde la última vez que hablamos?" — y el servidor tiene que entregar creaciones, modificaciones y eliminaciones desde un punto de referencia que la propia app guarda.

De ahí se desprenden tres exigencias:

  • La eliminación pasa a ser una marca, no una remoción. Si el registro simplemente desaparece de la base, no aparece en la lista de cambios y la aplicación nunca se entera de que tiene que sacarlo de la pantalla del usuario.
  • El orden importa. Los registros que dependen de otros tienen que subir y bajar en la secuencia correcta — la región antes que el cliente, el cliente antes que la visita.
  • Envío antes que recepción. La aplicación primero manda lo que está en la cola y solo después pregunta qué hay de nuevo — en el orden inverso, la versión vieja del servidor vuelve por encima de un cambio que todavía no subió.

Y está el recorte por permiso, que es la optimización más subestimada del tema. En Reticar, el vendedor solo recibe en el dispositivo lo que tiene derecho a ver: las visitas de las que es responsable y los clientes de las regiones a las que está vinculado. La base tiene 3.819 clientes; lo que baja a cada celular es una fracción de eso — lo que mejora descarga, consumo de memoria y seguridad al mismo tiempo, porque el dato que no baja no se filtra si se pierde el aparato.

Y el esfuerzo merece dimensionarse con honestidad: instrumentar cada entidad para participar de la sincronización es trabajo manual. En el proyecto de Reticar, ese módulo del servidor supera las 1.300 líneas. No es una llave que se enciende.

Qué no va al dispositivo#

Esta es la decisión que más dinero ahorra en un proyecto offline, y es de producto, no de ingeniería. El criterio no es la importancia del dato — es si tiene fin.

Tipo de dato¿Va al dispositivo?Ejemplo real
Catálogo y dato de referenciaSí, solo lecturaservicios, repuestos y regiones en la app de Reticar; ejercicios y alimentos en la app de Team Garin
Dato operativo del usuario, acotadoSí, con ida y vueltala visita del vendedor; el perfil y el cuestionario del alumno
Historial ilimitadoNoentrenamientos y dietas ya realizados: la conclusión se encola y se envía, pero el historial se consulta en la API cuando el alumno lo pide
Dato que exige tiempo real o integraciónNoconsulta a un sistema de terceros, y el módulo de inteligencia artificial de la app de entrenamiento
Dato que no es del usuarioNo bajaclientes de otras regiones, en la app del vendedor

La línea del historial es la que más discusión genera en una reunión de alcance, y es la más fácil de defender: el historial crece para siempre, y nada que crece para siempre entra en un dispositivo. Así definimos el alcance offline de la aplicación de la consultoría deportiva Team Garin, hoy convirtiéndose en un producto SaaS: el alumno necesita registrar el entrenamiento de hoy sin señal — no necesita cargar dos años de entrenamientos en el bolsillo para eso.

El mismo razonamiento, aplicado al volumen, resolvió la app de campo del sistema de gestión genética de DGA Intelligence: el rodeo es demasiado grande para bajar entero, así que la aplicación sincroniza solo los animales con situación activa, y lo que sale de ese conjunto se elimina del dispositivo en la sincronización siguiente.

También está el caso en que el offline tiene que cubrir la operación entera porque efectivamente ocurre sin señal: es lo que hacemos en la app de gestión de activos y hardware de GT, cuya operación visitamos en campo para remodelar la aplicación — el registro de esa visita está en YouTube.

Conflicto, y qué pasa con la escritura que el servidor rechaza#

Dos personas editan el mismo registro sin señal. Cuando se reconectan, el patrón más común — y el que usamos — es simple: prevalece el último cambio que llega al servidor, sin fusión y sin aviso. Para altas y registros de campo, donde cada persona toca lo suyo, alcanza. Para edición colaborativa del mismo documento, no — y fusionar campo por campo cuesta bastante más, así que la decisión pertenece al alcance.

Existe un segundo caso, menos discutido y más incómodo: la escritura que el servidor rechaza en definitiva. Un registro creado sin conexión que viola una regla de validación será rechazado hoy, mañana y siempre. Como la cola está ordenada, esa entrada traba todo lo que está detrás.

La salida habitual es descartar la entrada después de una cantidad de intentos, para destrabar el resto. Eso es razonable, y tiene un efecto colateral que hay que decir en voz alta: el registro sigue en el dispositivo marcado como no sincronizado, para siempre — sin explicación del motivo y sin camino para resolverlo. En la app de Reticar, cada orden de servicio lleva ese estado en un ícono propio, sincronizada o no; lo que el ícono no cuenta es si todavía hay esperanza.

No existe una respuesta única — existe una decisión consciente. Avisar al usuario, mandar el registro a un área de cuarentena o aceptar la pérdida son caminos con costos distintos; el error es no elegir. Offline-first garantiza que el equipo puede trabajar sin señal; no garantiza por sí solo que todo lo que se cargó llegó.

Preguntas frecuentes#

¿Offline-first es lo mismo que caché o PWA?#

No. La caché guarda la respuesta de una petición que ya ocurrió y sirve para acelerar la lectura. Offline-first es que la aplicación tenga una base de datos propia en el dispositivo como fuente de lo que aparece en pantalla, incluido lo que el usuario crea sin señal. La prueba práctica: en modo avión, una app con caché muestra lo que ya se vio; una app offline-first permite dar de alta algo nuevo, y ese registro sobrevive a cerrar y volver a abrir la aplicación.

Mi aplicación ya tiene modo offline. ¿Con eso alcanza?#

Depende de cómo se comporta con conexión mala, que es distinto de conexión ausente. Muchas apps con modo offline sincronizan todo al abrir y bloquean la interfaz mientras eso ocurre — en una red lenta, el resultado es peor que no tener offline. Las señales de que no alcanza son: la app se traba al abrir, tarda sin explicar qué está haciendo, o no deja claro si lo que se registró ya subió.

¿Se puede agregar offline después de que la aplicación ya está lista?#

Se puede, pero no es un ajuste en la aplicación: es un cambio en el servidor también. La API tiene que pasar a responder "qué cambió desde tal punto", aceptar registros con identificador generado por el propio dispositivo y marcar las eliminaciones en lugar de borrar de verdad. Por eso la conversación de offline empieza por el equipo de backend, no por el de mobile.

¿Necesito offline si mi equipo trabaja solo en zona urbana?#

Probablemente no por el motivo que imaginás, pero tal vez sí por otro. El criterio no es la ciudad, es dónde ocurre el trabajo: subsuelos, galpones, ascensores, estacionamientos y edificios industriales tumban la señal dentro de una capital. Si la persona usa el sistema sentada, con Wi-Fi, offline-first es costo sin retorno.

¿Qué pasa si dos personas editan el mismo registro sin conexión?#

En el patrón más común, prevalece el último cambio que llega al servidor, sin aviso y sin fusión. Eso es aceptable para altas y registros de campo, donde cada persona toca lo suyo, y es insuficiente para edición colaborativa del mismo documento. Conviene decidirlo en el alcance, porque la alternativa — fusionar cambio por campo — cuesta considerablemente más.

Fuentes#

Próximo paso#

Si tu equipo trabaja donde la señal falla, el punto de partida no es elegir tecnología: es decidir qué necesita funcionar sin red y qué no va al dispositivo. Así reemplazamos el sistema comercial de campo de Reticar Motores — y es el tipo de decisión que tratamos en sistemas a medida.

Compartir

Sigue por aquí

Más sobre Decidir y comprar software a medida

Contacto

Conversemos sobre tu proyecto

Cuéntanos qué necesitas resolver. Respondemos rápido, con gente que entiende de tecnología y de negocio.

¿Prefieres hablar directamente?

Elige el canal que prefieras. Respondemos rápido, en horario comercial.

De la primera conversación al go-live: eficiencia, seguridad e innovación.