Si estás construyendo una app Flutter que tiene que funcionar sin conexión, en 2026 tienes dos caminos. Uno es adoptar un sync engine (PowerSync, ElectricSQL, Zero) que sincroniza casi de fábrica una base SQLite en el dispositivo con tu base de datos de servidor. El otro es construir tu propia capa con SQLite, una cola de operaciones y tus reglas de conflicto. La respuesta corta: un sync engine te ahorra meses cuando muchos usuarios editan los mismos datos y tu interfaz tiene que reaccionar en vivo; una capa propia sigue ganando cuando tu offline es de un solo escritor por registro y necesitas que las reglas de conflicto sean tuyas. Y hay una trampa que conviene saber antes de elegir: ninguno de los dos te libra de la parte difícil, que es decidir qué pasa cuando dos versiones del mismo dato chocan.

Qué es un sync engine (y qué no)

Un sync engine mantiene una base de datos embebida en el cliente, casi siempre SQLite, sincronizada en segundo plano con la base de datos del servidor. Escribes y lees en local, la interfaz responde al instante, y la sincronización con el backend ocurre de forma asíncrona cuando hay red. Frente a un REST tradicional con caché, la diferencia es que el dispositivo trabaja siempre contra su propia base de datos y nunca depende de la latencia de una petición para pintar la pantalla.

Eso es lo que promete el paradigma local-first. La pregunta de arquitectura no es si el local-first es bueno (para muchas apps lo es), sino quién escribe esa capa de sincronización: un producto de terceros o tu equipo.

El mapa en 2026

El espacio se ha ordenado alrededor de tres motores acoplables y una capa cliente que se apoya en ellos.

MotorBackendSoporte FlutterOfflineConflictosHosting
PowerSyncPostgres, MongoDB, MySQL, SQL ServerSDK Dart de primera claseCompleto, SQLite realLos defines tú en tu API de subidaCloud y self-host
ElectricSQLSolo PostgresEnfocado a React y React NativeSí, SQLite/PGliteLast-write-wins por defectoOpen source, self-host
ZeroAgnóstico, orientado a PostgresSolo web, sin móvilLecturas en caché y cola de escriturasServer-authoritativeOpen source, cloud por llegar

A esto se suma TanStack DB (2025), que no es un motor sino una capa de datos reactiva en el cliente con mutaciones optimistas que se enchufa a uno de esos motores. Y esto sigue moviéndose: Supabase compró Triplit en 2025.

Para Flutter, la lista se acorta rápido. PowerSync es hoy el único con un SDK de Dart maduro y el mejor soporte offline. ElectricSQL y Zero miran sobre todo a React; su historia en móvil nativo o Flutter va por detrás. Si tu app es Flutter y necesitas un sync engine en producción este año, en la práctica hablamos de PowerSync. Decirlo así te ahorra semanas de evaluar opciones que aún no están listas para tu stack.

Lo que un sync engine no te resuelve

Aquí es donde se cae el discurso de "0 ms de latencia y sincronización mágica". Un sync engine mueve datos entre el dispositivo y el servidor. No decide por ti las cosas que de verdad duelen:

La semántica de conflicto de tu dominio la sigues poniendo tú. Last-write-wins, el valor por defecto de ElectricSQL, es cómodo hasta que dos comerciales editan el mismo pedido sin cobertura y el que sincroniza más tarde pisa el trabajo del otro sin avisar. En un inventario que no puede quedar en negativo, o en un historial clínico, esa pérdida silenciosa es inaceptable. PowerSync te da libertad total, pero esa libertad significa que la lógica de conflicto la escribes en tu API de subida. El motor no te ahorra pensarla.

Modelar qué porción de los datos vive en cada dispositivo tampoco es gratis. Las sync rules de PowerSync o las shapes de ElectricSQL son código que hay que diseñar y mantener: qué filas se replican a quién, cómo cambia eso según el rol del usuario, qué pasa cuando alguien cambia de permisos. Es un modelo de datos nuevo encima del que ya tienes.

Las migraciones de esquema se complican. Ahora tienes un esquema en el servidor y otro en miles de dispositivos que pueden estar semanas sin abrir la app. Cada cambio hay que pensarlo hacia atrás y hacia delante.

Y el dato en local sigue siendo tu responsabilidad. La base SQLite del dispositivo va sin cifrar salvo que lo montes tú, con SQLCipher o equivalente. Si guardas datos sensibles, el sync engine no te cubre el cifrado en reposo.

A cambio de todo esto añades una pieza más a tu infraestructura y, con ElectricSQL, la obligación de que tu backend sea Postgres. Son costes reales, no letra pequeña.

Cuándo construimos la capa nosotros

En las apps de reparto y logística que hemos construido, la mayoría de conflictos se previenen por diseño antes de que existan. Un evento de entrega lo genera una sola persona, en un solo dispositivo, en un momento concreto. El resto de la app son consultas. Cuando tu offline es de un solo escritor por registro y sobre todo append-only, un sync engine es sobreingeniería: SQLite con Drift, una cola de operaciones idempotentes y sincronización diferida cuando vuelve la red resuelven el caso completo con menos piezas móviles y sin acoplar el backend a nadie.

El otro escenario donde preferimos capa propia es cuando las reglas de conflicto son reglas de negocio. Si "el stock no puede quedar negativo" o "gana la firma del supervisor, no la más reciente" son decisiones del producto, las queremos en nuestro código, versionadas y testeadas con el resto de la lógica, no delegadas al last-write-wins de una librería. Ya escribimos sobre cómo resolvemos esto con CRDT y sincronización offline-first en Flutter y sobre qué sincronizar en una app de reparto sin cobertura.

Construir tu capa tiene un coste que no escondemos: la escribes, la pruebas y la mantienes tú. Pero para un offline single-writer es menos código del que parece, y te quedas sin dependencias externas en el camino crítico de tu producto.

Cuándo adoptamos un sync engine

El cálculo cambia cuando hay colaboración de verdad. Muchos usuarios editando los mismos registros, una interfaz que tiene que reflejar al instante lo que hacen otros, live queries que se actualizan solas. Reconstruir eso a mano es escribir tu propio motor de sincronización, y ahí sí que casi siempre pierdes: acabas manteniendo un producto entero para el que ya existe una alternativa probada.

Si tu backend ya está en Postgres, tu equipo es Flutter y necesitas ese nivel de reactividad multiusuario, PowerSync es la opción sensata en 2026. Te comes la curva de las sync rules, pero te ahorras la parte más frágil de un local-first serio. El resto de motores, para Flutter, todavía no están.

Cómo lo decidimos

Cuando un cliente nos plantea esto en Discovery, la decisión sale de cinco preguntas:

  • ¿Cuántas personas escriben el mismo registro? Uno solo empuja hacia capa propia; muchos, hacia sync engine.
  • ¿Necesitas que la pantalla refleje en vivo los cambios de otros usuarios? Si sí, un motor con live queries te ahorra mucho.
  • ¿Tu backend es Postgres o puede serlo? Es un requisito duro para casi todos los motores.
  • ¿El offline es el modo principal de la app o un modo degradado? Cuanto más central, más te compensa que alguien mantenga esa capa por ti, o más control propio vas a querer.
  • ¿Puedes asumir una dependencia más en tu infraestructura y en el camino crítico del producto?

No hay respuesta universal, y desconfía de quien te la dé. Un sync engine no es más moderno que una capa propia, ni al revés; son herramientas para problemas distintos. Lo que sí es constante es que la parte difícil, decidir qué gana cuando dos datos chocan, la vas a diseñar tú en ambos casos.

Si estás en esa decisión para una app Flutter con requisitos serios de offline, es exactamente el tipo de trade-off que desmontamos en la fase de discovery antes de escribir una línea. Puedes ver cómo trabajamos el desarrollo de apps Flutter o contarnos tu caso.