La evolución del desarrollo web ha priorizado la velocidad y la reactividad en el cliente. Sin embargo, el 'alpha' restante para mejoras significativas en la experiencia de usuario y desarrollador reside en extender la reactividad más allá del cliente, abarcando el servidor. Este enfoque, denominado 'sync-based architecture', busca eliminar la latencia inherente a las operaciones de fetching tradicionales, que implican comunicación de red explícita y costosa. Al abstraer la red y sincronizar el estado reactivamente entre cliente y servidor, se logran actualizaciones instantáneas, resiliencia ante la conectividad y soporte nativo para colaboración en tiempo real, un requisito fundamental para los sistemas 'agentic' modernos.
Históricamente, construir sistemas de sincronización robustos ha requerido equipos de ingeniería de élite y una inversión considerable, debido a la complejidad de los sistemas distribuidos. Sin embargo, la madurez de nuevas herramientas y plataformas está democratizando esta capacidad, permitiendo a equipos más pequeños adoptar arquitecturas que antes eran exclusivas de gigantes tecnológicos. La tesis central es que la sincronización reactiva extremo a extremo no solo mejora la velocidad y la colaboración, sino que también simplifica el desarrollo de aplicaciones, especialmente en el contexto de la generación de código por LLMs, al reemplazar el 'fetch spaghetti' con data bindings declarativos.
Arquitectura del Sistema
La arquitectura propuesta se basa en un motor de sincronización (Electric) y una base de datos reactiva del lado del cliente (TanStack DB). Electric se encarga de la sincronización de datos de la ruta de lectura (read-path sync) con replicación parcial y fan-out. Monitorea el flujo de replicación lógica de una base de datos PostgreSQL estándar y entrega subconjuntos de datos relevantes a cada cliente. La entrega de datos se realiza a través de un protocolo HTTP basado en long polling, que permite el uso de infraestructura CDN existente (como Cloudflare o Fastly) para caching y coalescing de solicitudes, mejorando la escalabilidad y reduciendo la carga en el origen.
TanStack DB, por su parte, es una base de datos del lado del cliente consciente de la sincronización. Proporciona primitivas de 'collection' para almacenar datos localmente, 'live queries' que se actualizan en sub-milisegundos mediante un motor de 'differential dataflow' (similar a Dataflow de Google o Materialize), y 'mutations' optimistas transaccionales. Estas mutaciones permiten escrituras locales instantáneas que se sincronizan en segundo plano con el servidor. El sistema gestiona automáticamente el ciclo de vida del estado optimista, incluyendo el descarte cuando la transacción se confirma desde el servidor o el rollback en caso de error. La integración con Electric se realiza a través de 'electricCollection', que utiliza el cliente TypeScript de bajo nivel de Electric para la sincronización. La característica 'query-driven sync' permite que los predicados de las 'live queries' del cliente se 'empujen' al motor de sincronización, solicitando dinálogos dinámicos de datos adicionales bajo demanda, optimizando la carga inicial y la navegación.
Flujo de Escritura Optimista y Sincronización
- 1 Vista Usuario realiza una escritura local (ej. añadir ítem)
- 2 TanStack DB Client Aplica estado optimista instantáneamente a la colección local
- 3 Vista Se re-renderiza con el estado optimista, usuario ve el cambio al instante
- 4 TanStack DB Client Envía la escritura al backend en segundo plano
- 5 Backend/API Procesa la escritura y la persiste en PostgreSQL
- 6 Electric Sync Engine Monitorea la replicación lógica de PostgreSQL, detecta el cambio
- 7 Electric Sync Engine Sincroniza el cambio de vuelta al cliente (vía CDN/long polling)
- 8 TanStack DB Client Actualiza la colección local con el estado final, descarta el optimista
Flujo de Sincronización Basada en Consulta (Query-Driven Sync)
- 1 Componente Cliente Define una 'live query' con predicados dinámicos (ej. `projectId`)
- 2 TanStack DB Client Detecta cambio en el predicado de la 'live query' (ej. usuario navega)
- 3 TanStack DB Client Empuja la demanda del predicado a la 'electricCollection'
- 4 Electric Sync Engine Recibe el predicado, lo combina con la 'shape' de la suscripción
- 5 Electric Sync Engine Genera una solicitud de 'snapshot' para el subconjunto de datos
- 6 PostgreSQL Proporciona los datos que coinciden con el subconjunto
- 7 Electric Sync Engine Sincroniza los datos adicionales al cliente
- 8 TanStack DB Client Añade los nuevos datos a la colección local, actualiza 'live queries'
| Capa | Tecnología | Justificación |
|---|---|---|
| storage | PostgreSQL | Base de datos primaria del lado del servidor, fuente de verdad para los datos. Soporta replicación lógica, esencial para que Electric monitoree los cambios. Logical Replication |
| data-processing | Electric Sync Engine | Motor de sincronización de datos que monitorea PostgreSQL y entrega cambios reactivamente a los clientes. Realiza replicación parcial y fan-out. |
| cache | CDN (Cloudflare, Fastly) | Utilizado para la entrega de datos del motor de sincronización. Permite caching de cargas iniciales y 'request coalescing' para reducir la carga en el origen y mejorar la escalabilidad. |
| compute | TanStack DB | Base de datos reactiva del lado del cliente. Gestiona colecciones de datos, 'live queries' y mutaciones optimistas. Proporciona un motor de 'differential dataflow' para actualizaciones de UI sub-milisegundo. vs RxDB, PowerSync, Convex, Ditto, Instant, LiveStore, Jazz, Zero (Rocicorp) syncMode: on-demand |
| networking | HTTP Long Polling | Protocolo de comunicación entre el cliente y el motor de sincronización. Elegido sobre WebSockets por su naturaleza stateless, que simplifica la escalabilidad y el uso de CDNs. vs WebSockets, Server-Sent Events (SSE) |
Trade-offs
Ganancias
- ▲▲ Latencia de UI
- ▲ Experiencia de Usuario (UX)
- ▲ Experiencia de Desarrollador (DX)
- ▲ Resiliencia de Conectividad
- ▲ Colaboración en Tiempo Real
Costes
- ▲ Complejidad de Implementación Inicial (sin herramientas)
- ▲ Lock-in a stacks 'greenfield' (con soluciones monolíticas)
import { useQuery, useMutation, QueryClient } from '@tanstack/react-query';
const queryClient = new QueryClient();
function useTodos() {
return useQuery({
queryKey: ['todos'],
queryFn: async () => {
const response = await fetch('/api/todos');
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
},
});
}
function useAddTodo() {
return useMutation({
mutationFn: async (newTodo) => {
const response = await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newTodo),
});
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
},
onMutate: async (newTodo) => {
// Optimistic update
await queryClient.cancelQueries({ queryKey: ['todos'] });
const previousTodos = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], (old) => [...(old || []), { id: 'optimistic', ...newTodo }]);
return { previousTodos };
},
onError: (err, newTodo, context) => {
// Rollback on error
queryClient.setQueryData(['todos'], context?.previousTodos);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
}import { createElectricCollection } from '@electric-sql/tanstack-db';
import { ElectricClient } from '@electric-sql/client';
const electric = new ElectricClient(); // Initialized Electric client
const projectsCollection = createElectricCollection({
electric,
collection: 'projects',
syncMode: 'on-demand',
// ... other configuration like schema
});
function useProjectIssues(projectId) {
return projectsCollection.liveQuery((db) =>
db.issues.where({ projectId }).orderBy('priority').toArray()
);
}Fundamentos Teóricos
El concepto de sincronización de estado reactivo y la gestión de consistencia en sistemas distribuidos tienen profundas raíces en la investigación académica. Los 'CRDTs' (Conflict-free Replicated Data Types), mencionados en el artículo, son un pilar fundamental para el software 'local-first' y la colaboración en tiempo real, permitiendo la convergencia automática de datos sin necesidad de coordinación centralizada. Autores como Marc Shapiro, Nuno Preguiça y Marek Zawirski han contribuido significativamente a la teoría y práctica de los CRDTs desde principios de los 2010s.
El uso de 'differential dataflow' para 'live queries' en TanStack DB, que propaga deltas en lugar de re-ejecutar consultas completas, se alinea con principios de sistemas de procesamiento de flujos de datos y mantenimiento de vistas materializadas incrementales, como los explorados en trabajos de Michael Stonebraker sobre bases de datos activas o más recientemente en sistemas como Noria o Materialize. La abstracción de la red y la gestión de estado optimista también se relaciona con los principios del teorema CAP (Consistencia, Disponibilidad, Tolerancia a Particiones) y PACELC (Latencia, Consistencia, Disponibilidad, Tolerancia a Particiones, Costo, Complejidad), donde la elección de la consistencia eventual y la disponibilidad local son trade-offs conscientes para mejorar la experiencia de usuario y la resiliencia.