Universal SQLite Synchronization Core - A dependency-grade, local-first, offline-first SQLite synchronization primitive
Project description
sqlite-sync-core
A deterministic, infrastructure-free, local-first SQLite synchronization engine designed for offline-critical and privacy-sensitive systems.
Built by VisionQuantech, India ๐ฎ๐ณ
Why sqlite-sync-core?
| Feature | sqlite-sync-core | Firebase | Supabase |
|---|---|---|---|
| No server required | โ | โ | โ |
| Works offline | โ | โ ๏ธ Limited | โ ๏ธ Limited |
| Transport agnostic | โ USB, Email, HTTP, WS | Proprietary | WebSocket only |
| Explicit conflicts | โ Never auto-overwrites | โ LWW | โ LWW |
| Deterministic replay | โ Git-like correctness | โ | โ |
| No telemetry | โ | โ | โ |
| Self-hosted | โ | โ | โ |
Installation
# Basic installation
pip install sqlite-sync-core
# With HTTP server support
pip install sqlite-sync-core[server]
# With encryption support
pip install sqlite-sync-core[crypto]
# Everything
pip install sqlite-sync-core[all]
Quick Start
Initialize a Sync-Enabled Database
from sqlite_sync import SyncEngine
engine = SyncEngine("my_app.db")
device_id = engine.initialize()
# Create your table
engine.connection.execute("""
CREATE TABLE todos (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
done INTEGER DEFAULT 0
)
""")
# Enable sync for this table
engine.enable_sync_for_table("todos")
# All changes are now automatically captured!
engine.connection.execute("INSERT INTO todos (title) VALUES ('Buy milk')")
engine.connection.commit()
Sync via File Transfer (USB, Email, Cloud Drive)
# Device A: Generate bundle
bundle_path = engine_a.generate_bundle(
peer_device_id=device_b_id,
output_path="sync_bundle.db"
)
# Send bundle_path via any method: USB, email, Dropbox, etc.
# Device B: Import bundle
result = engine_b.import_bundle("sync_bundle.db")
print(f"Applied: {result.applied_count}, Conflicts: {result.conflict_count}")
Sync via HTTP (Real-time)
from sqlite_sync.transport import HTTPTransport
from sqlite_sync.sync_loop import SyncLoop, SyncLoopConfig
# Create transport
transport = HTTPTransport(
base_url="http://localhost:8080",
device_id=engine.device_id
)
# Create background sync loop
sync_loop = SyncLoop(
engine=engine,
transport=transport,
config=SyncLoopConfig(interval_seconds=30)
)
await sync_loop.start() # Syncs automatically in background
Sync via WebSocket (Real-time Bidirectional)
from sqlite_sync.transport import WebSocketTransport
transport = WebSocketTransport(
url="ws://localhost:8765",
device_id=engine.device_id,
on_operation_received=lambda op: print(f"Received: {op.op_type}")
)
await transport.connect()
await transport.send_operations(engine.get_new_operations())
Conflict Resolution
sqlite-sync-core detects conflicts but gives YOU control over resolution.
Built-in Strategies
from sqlite_sync.resolution import ResolutionStrategy, get_resolver
# Last-Write-Wins (simple but may lose data)
resolver = get_resolver(ResolutionStrategy.LAST_WRITE_WINS)
# Field-level merge (preserves non-conflicting fields)
resolver = get_resolver(ResolutionStrategy.FIELD_MERGE, prefer_local=True)
# Manual (keep for user review)
resolver = get_resolver(ResolutionStrategy.MANUAL)
# Custom (your business logic)
def my_resolver(context):
# Your logic here
return ResolutionResult(resolved=True, winning_op=context.local_op, ...)
resolver = get_resolver(ResolutionStrategy.CUSTOM, resolver_fn=my_resolver)
Handle Conflicts
conflicts = engine.get_unresolved_conflicts()
for conflict in conflicts:
print(f"Conflict on {conflict.table_name}, row {conflict.row_pk.hex()}")
print(f"Local op: {conflict.local_op_id.hex()}")
print(f"Remote op: {conflict.remote_op_id.hex()}")
Advanced Features
Log Compaction
from sqlite_sync.log_compaction import LogCompactor
compactor = LogCompactor(engine.connection)
# Create snapshot for new devices
snapshot = compactor.create_snapshot()
# Prune old operations
compactor.prune_acknowledged_ops(safe_op_id)
# Full compaction
result = compactor.compact_log()
print(f"Removed {result.ops_removed} operations")
Schema Evolution
from sqlite_sync.schema_evolution import SchemaManager
schema = SchemaManager(engine.connection)
# Safe column addition (syncs across devices)
migration = schema.add_column(
table_name="todos",
column_name="priority",
column_type="INTEGER",
default_value=1
)
# Check compatibility
if schema.check_compatibility(remote_version=1):
print("Compatible!")
Security
from sqlite_sync.security import SecurityManager
security = SecurityManager(
device_id=engine.device_id,
signing_key=my_secret_key
)
# Sign bundles
signed = security.sign_bundle(bundle_data)
# Encrypt bundles (requires cryptography package)
encrypted = security.encrypt_bundle(bundle_data, password="secret")
decrypted = security.decrypt_bundle(encrypted, password="secret")
Crash Safety
from sqlite_sync.crash_safety import CrashSafeExecutor
executor = CrashSafeExecutor(engine.connection)
# Resume after crash
checkpoint = executor.get_incomplete_checkpoint()
if checkpoint:
print(f"Resuming from {checkpoint.last_applied_op_id.hex()}")
# Atomic operations
with executor.atomic_operation():
engine.apply_operation(op1)
engine.apply_operation(op2) # Both or neither
Run the Sync Server
# Start HTTP sync server
python -m sqlite_sync.server.http_server
# Or in code
from sqlite_sync.server import run_server
run_server(host="0.0.0.0", port=8080)
Examples
See the examples/ directory:
| Example | Description |
|---|---|
basic_usage.py |
Simple CLI sync demo |
desktop_demo.py |
Local sync between databases |
http_sync_demo.py |
Client/server network sync |
network_sync.py |
WebSocket real-time sync |
Core Invariants
| # | Invariant | Description |
|---|---|---|
| 1 | Append-only | Operations never modified |
| 2 | Causal consistency | Vector clocks ensure ordering |
| 3 | Deterministic | Same ops = same result everywhere |
| 4 | Explicit conflicts | Never silently overwrites |
| 5 | Idempotent | Import same bundle N times = same result |
| 6 | Transport agnostic | Bundles work anywhere |
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Application โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ SyncEngine โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Capture โ โ Resolution โ โ Schema Evolution โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Bundle โ โ Compaction โ โ Security โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Transport Layer (Pluggable) โ
โ โโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ HTTP โ โ WebSocket โ โ File โ โ Custom/P2P โ โ
โ โโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Use Cases
- Offline-first mobile apps - Works without internet
- Air-gapped systems - Defense, government, NGOs
- Privacy-sensitive applications - Medical, legal, finance
- Field operations - Works with USB/SD card transfer
- Embedded systems - IoT with intermittent connectivity
- Multi-device personal apps - Notes, todos, journals
License
Dual License:
| Use Case | License | Cost |
|---|---|---|
| Personal/Open Source | AGPL-3.0 | Free |
| Commercial/Proprietary | Commercial | Paid |
Contact for commercial licensing:
Contributing
- Fork the repository
- Create a feature branch
- Run tests:
pytest tests/ -v - Submit a pull request
Built with โค๏ธ for offline-first applications
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sqlite_sync_core-0.2.0.tar.gz.
File metadata
- Download URL: sqlite_sync_core-0.2.0.tar.gz
- Upload date:
- Size: 79.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
304e5b03cbf48f2d7efa55b1250262903cab60cad2a63583c17a81675ae0925f
|
|
| MD5 |
0017524224214fffc6bf8d3d352ad5b6
|
|
| BLAKE2b-256 |
b56f88068b2e28b3f0df22317935c8e42724423ad126b14e5a812525e3a8a80c
|
File details
Details for the file sqlite_sync_core-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sqlite_sync_core-0.2.0-py3-none-any.whl
- Upload date:
- Size: 90.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26987840aa3830d25d82474d0d68262d6c18d698130440c0d4f8e5ad02f4b8f1
|
|
| MD5 |
ccef2f5f74d318d80e026099fb1c3806
|
|
| BLAKE2b-256 |
828b730fa3efd95792cab7775d540144610e7ba6e655c061064c0ccb2c9673eb
|