Tipos de Datos Replicados Libres de Conflictos para Rust
Ligero (~50KB), compatible con no_std, optimizado para IoT, edge computing, WASM y arquitecturas local-first.
cargo add crdt-kit --features serde ¿Qué son los CRDTs?
Los Conflict-Free Replicated Data Types son estructuras de datos que pueden replicarse en múltiples dispositivos, actualizarse de forma independiente y concurrente, y fusionarse automáticamente sin conflictos.
A diferencia de las bases de datos tradicionales que requieren un servidor central, los CRDTs garantizan que todas las réplicas convergerán al mismo estado sin importar el orden de las actualizaciones.
Esto los hace ideales para apps offline-first, sistemas P2P, redes IoT y cualquier escenario donde los dispositivos necesiten trabajar independientemente.
Tres dispositivos crean datos de forma independiente sin conexión a la red.
¿Por qué crdt-kit?
Construido para entornos con recursos limitados donde las soluciones existentes agregan demasiado overhead.
Funcionalidades
no_std
Corre en bare metal, Raspberry Pi, ESP32. Todos los tipos funcionan con #![no_std] + alloc.
Delta Sync
Solo envía lo que cambió. Trait DeltaCrdt para GCounter, PNCounter, ORSet. Minimiza ancho de banda.
WASM
Bindings wasm-bindgen de primera clase. Mismos CRDTs en navegador, Deno, Node.js y backend Rust.
Migrations
Migraciones transparentes y lazy al leer. Proc macros #[crdt_schema] + #[migration]. Determinístico.
Storage
Tres backends: SQLite (bundled), redb (Rust puro), memoria. Event sourcing, snapshots, compactación.
Codegen
Define entidades en TOML, ejecuta crdt generate. Obtén modelos, migraciones, repositorios, eventos, sync.
Serde
Serialize/Deserialize para los 9 tipos CRDT. JSON, MessagePack, Postcard, CBOR — cualquier formato serde.
Events
Log de eventos completo con append, replay, snapshots, compactación. Trait EventStore en todos los backends.
Dev Tools
CLI: status, inspect, compact, export, generate, dev-ui. Panel web para inspección visual.
Comparación
| crdt-kit | Automerge | Yjs / Yrs | |
|---|---|---|---|
| Language | Rust | Rust | JS / Rust |
| Zero deps (core) | ✓ | 30+ | N/A |
| no_std | ✓ | ✗ | ✗ |
| WASM | ✓ | Partial | Native |
| Storage | SQLite, redb, mem | Custom | N/A |
| Migrations | Automatic | Manual | N/A |
| Delta sync | ✓ | ✓ | ✓ |
| Event sourcing | ✓ | ✗ | ✗ |
| Code generation | ✓ | ✗ | ✗ |
| CLI | ✓ | ✗ | ✗ |
| Size | ~50KB | ~500KB+ | ~150KB |
9 Tipos de CRDT
Desde contadores hasta texto colaborativo. Todos Send + Sync, serde-ready, convergentes.
Contadores
Registros
Conjuntos
Inicio Rápido
[dependencies]
crdt-kit = "0.3" use crdt_kit::prelude::*;
// Two devices, working offline
let mut phone = GCounter::new("phone");
phone.increment();
phone.increment();
let mut laptop = GCounter::new("laptop");
laptop.increment();
// Reconnect — merge. Always converges.
phone.merge(&laptop);
assert_eq!(phone.value(), 3); Delta Sync
let mut sensor = GCounter::new("sensor-a");
sensor.increment_by(142);
let mut gateway = GCounter::new("gateway");
// Delta: only send what the gateway doesn't have
let delta = sensor.delta(&gateway);
gateway.apply_delta(&delta);
assert_eq!(gateway.value(), 142); Schema Migrations
use crdt_migrate::{crdt_schema, migration};
#[crdt_schema(version = 1, table = "sensors")]
struct SensorV1 { device_id: String, temperature: f32 }
#[crdt_schema(version = 2, table = "sensors")]
struct SensorV2 { device_id: String, temperature: f32, humidity: Option<f32> }
#[migration(from = 1, to = 2)]
fn add_humidity(old: SensorV1) -> SensorV2 {
SensorV2 { device_id: old.device_id, temperature: old.temperature, humidity: None }
}
// v1 records auto-migrate to v2 on load Arquitectura
Workspace multi-crate. Cada crate versionado independientemente. Usa solo lo que necesites.
Definir
Escribe un crdt-schema.toml con entidades, versiones, campos CRDT y relaciones.
Generar
Ejecuta crdt generate. Obtén modelos, migraciones, traits de repositorio, eventos, sync.
Usar
Importa Persistence<S> en tu app. Accede a repositorios, almacena datos, sincroniza.
Casos de Uso
IoT y Sensores
Core no_std en ESP32, Raspberry Pi. Delta sync por LoRa/BLE. Migraciones manejan OTA.
Apps Móviles
Offline-first. Edita sin red. Los cambios se fusionan automáticamente al reconectar.
Colaboración en Tiempo Real
TextCrdt para edición estilo Google Docs. ORSet para colecciones. Sin coordinador central.
Edge Computing
CRDTs en nodos edge de CDN. Escrituras locales, delta sync. Backend redb puro Rust.
Redes P2P
Sin servidor. Cada peer es igual. Cualquier transporte: WebSocket, WebRTC, Bluetooth.
WASM y Navegador
Misma lógica en backend Rust y navegador. Bindings wasm-bindgen. Un solo codebase.
Ecosistema
7 crates, versionados independientemente en crates.io. Usa solo lo que necesites.
crdt-kit
Librería principal
9 CRDTs listos para usar: GCounter, PNCounter, LWWRegister, MVRegister, GSet, TwoPSet, ORSet, RGA y TextCrdt. Incluye Hybrid Logical Clock (HLC) y traits para crear tus propios CRDTs.
crdt-store
Capa de persistencia
Guarda y carga CRDTs en SQLite, redb (embedded) o memoria. CrdtDb unifica el acceso: save(), load(), merge(), list_keys(). Namespaces para separar entidades.
crdt-migrate
Migraciones automáticas
Evoluciona tus structs sin perder datos. Define versiones con #[crdt_schema] y funciones #[migration]. Los registros se migran automáticamente al cargar.
crdt-codegen
Generador de código
Define entidades en un archivo TOML (schema.toml) y genera automáticamente: structs versionados, migraciones, repositorios y la capa de persistencia completa.
crdt-cli
Herramienta de línea de comandos
Inspecciona bases de datos, genera código, exporta JSON, compacta event logs y lanza el panel web. Todo desde la terminal con "crdt <comando>".
crdt-dev-ui
Panel web de inspección
Panel web embebido en localhost:4242. Navega namespaces, inspecciona entidades, ve event logs y vectores de estado. Dark theme integrado.
Demo Interactivo
Dos dispositivos, un chat. Envía mensajes offline, sincroniza — los CRDTs garantizan convergencia.
Rendimiento
Medido con Criterion en builds optimizados. 37–700x más rápido que Automerge y Yrs.
vs Automerge y Yrs
Benchmarks comparativos con las dos librerías CRDT más populares del ecosistema Rust.
Counter ×1000
crdt-kit 33 μs
Automerge 23 ms
Text insert 1000
crdt-kit 83 μs · Yrs 3.1 ms
Automerge 16.5 ms
List insert 1000
crdt-kit 265 μs · Yrs 16.5 ms
Automerge 34.4 ms
Set insert 1000
crdt-kit 203 μs
Automerge 27.6 ms
8M ops/sec GCounter increment
Incrementar un contador distribuido. La operación más básica y frecuente.
125 μs / 1000 ops ▼
¿Cómo funciona esta prueba?
Se crea un GCounter con un nodo y se llama .increment() 1000 veces consecutivas. Se mide el tiempo total. Un GCounter es un mapa {nodo → cantidad}. Cada increment solo suma 1 a su propio slot — O(1), sin locks.
4.5M merges/sec GCounter merge
Fusionar 10 réplicas. Simula 10 dispositivos reconectando a la vez.
2.2 μs / 10 replicas ▼
¿Cómo funciona esta prueba?
Se crean 10 GCounters con diferentes nodos, cada uno incrementado varias veces. Se fusionan todos en uno. Merge toma el max() de cada slot. Tiempo lineal respecto al número de nodos.
3.7M ops/sec Rga insert ×1000
Insertar 1000 elementos en una lista replicada. Para playlists, kanban.
267 μs / 1000 ops ▼
¿Cómo funciona esta prueba?
Rga usa un Vec plano con posicionamiento directo. No hay rebuild de la secuencia — cada insert encuentra su posición en O(n) amortizado. 62× más rápido que Yrs Y.Array, 130× más rápido que Automerge List.
4M ops/sec TextCrdt insert 1000
Insertar 1000 caracteres en texto colaborativo. Para editores en tiempo real.
246 μs / 1000 chars ▼
¿Cómo funciona esta prueba?
TextCrdt usa Vec plano con len() cacheado en O(1). Cada insert calcula la posición visible y coloca el elemento directamente. 37× más rápido que Yrs Y.Text, 199× más rápido que Automerge Text.
2.8M ops/sec ORSet insert ×1000
Insertar en un conjunto replicado. Para carritos de compra, listas.
350 μs / 1000 ops ▼
¿Cómo funciona esta prueba?
Cada insert genera un tag único (nodo + reloj lógico). En merge, "add gana" sobre remove concurrente. 136× más rápido que Automerge Map.
7.9M merges/sec LWWRegister merge
Last-Writer-Wins: el valor más reciente gana. Para perfiles, config, GPS.
12.6 μs / 100 replicas ▼
¿Cómo funciona esta prueba?
LWWRegister guarda un valor + timestamp (Hybrid Logical Clock). Al merge, gana el timestamp más alto. El merge es una simple comparación — O(1) por par.
Medido con Criterion en builds optimizados (release). μs = microsegundos. Comparado con Automerge 0.7 y Yrs 0.25. Haz clic en cada card para detalles.
Garantías Matemáticas
Todos los CRDTs satisfacen Strong Eventual Consistency (SEC). Verificado por 268 tests.
Conmutatividad
El orden de sync no importa.
Asociatividad
Agrupa los syncs como quieras.
Idempotencia
Seguro de reintentar. Sin duplicados.
CLI para Desarrolladores
$ crdt status app.db Vista general de la base de datos.
$ crdt inspect app.db sensor-42 Detalle de entidad con event log.
$ crdt compact app.db Snapshot + truncar event logs.
$ crdt export app.db --namespace sensors Exportar JSON.
$ crdt generate --schema schema.toml Generar capa de persistencia.
$ crdt dev-ui app.db Panel web en localhost:4242.
Empieza a construir offline-first
cargo add crdt-kit --features serde