Lessons learned from building a sync-engine and reactivity system with SQLite
Итоги постройки синхронизатора и реактивной системы на SQLite
Первый опыт: PGlite + Electric
- PostgreSQL в WASM + Electric даёт точную синхронизацию и LISTEN-реактивность.
- Недостатки: Electric ещё молод, старт до минуты без компакции; PGlite в single-user-режиме течёт памятью и тормозит при росте БД.
Переосмысление задачи
- SQLite-WASM стал зрелым; моё приложение однопользовательское и почти всегда онлайн.
- Значит, достаточно простого собственного решения.
Минимальный синхронизатор
- При первом запуске клиент вытягивает всё по
updated_at
. - Каждые 2–3 с опрашивает сервер за записями новее этой метки и делает upsert.
- Локально при каждом UPDATE ставится флаг
modified = 1
; фоновый процесс отправляет изменения. - Для текстов можно добавить CRDT (Yjs) на случай конфликтов.
Для отслеживания изменений используется триггер, который игнорируется во время синхронизации через таблицуsync_control
.
Реактивность на SQLite
- SQLite не умеет LISTEN, но:
- Триггер пишет в лог-таблицу пару «таблица + id».
- Broadcast Channel API рассылает это в другие вкладки/воркеры.
- UI подписывается на канал и перечитывает нужные строки.
- Использую wa-sqlite: стабильно, без сбоев с момента установки.
Комментарии (35)
- Сообщество обсуждает проблемы PGlite и Electric, поэтому Electric развивает Tanstack DB как «sync-native» JS-решение без привязки к бэкенду.
- Предлагаются альтернативы: Evolu, SQLite-Sync, CouchDB и CRDT-движки, но авторы предупреждают, что продакшен-синхронизация сложнее PoC.
- Некоторые отказались от SQLite в браузере вовсе, храня лишь простые индексы и рассылая дельты.
- Участники подчёркивают важность консенсуса (Lamport/CRDT/raft) и отмечают, что гранулярная синхронизация не гарантирует консистентность без транзакций или разрешения конфликтов.
- В итоге рекомендуют использовать готовые движки, а не изобретать велосипед, особенно если нужны офлайн, e2e-шифрование и многопользовательский доступ.