RepoPilotOpen in app →

orbitinghail/sqlsync

SQLSync is a collaborative offline-first wrapper around SQLite. It is designed to synchronize web application state between users, devices, and the edge.

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 6mo ago
  • 2 active contributors
  • Apache-2.0 licensed
Show all 8 evidence items →
  • CI configured
  • Tests present
  • Slowing — last commit 6mo ago
  • Small team — 2 contributors active in recent commits
  • Concentrated ownership — top contributor handles 76% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/orbitinghail/sqlsync)](https://repopilot.app/r/orbitinghail/sqlsync)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/orbitinghail/sqlsync on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: orbitinghail/sqlsync

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/orbitinghail/sqlsync shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 6mo ago
  • 2 active contributors
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Slowing — last commit 6mo ago
  • ⚠ Small team — 2 contributors active in recent commits
  • ⚠ Concentrated ownership — top contributor handles 76% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live orbitinghail/sqlsync repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/orbitinghail/sqlsync.

What it runs against: a local clone of orbitinghail/sqlsync — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in orbitinghail/sqlsync | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 199 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>orbitinghail/sqlsync</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of orbitinghail/sqlsync. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/orbitinghail/sqlsync.git
#   cd sqlsync
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of orbitinghail/sqlsync and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "orbitinghail/sqlsync(\\.git)?\\b" \\
  && ok "origin remote is orbitinghail/sqlsync" \\
  || miss "origin remote is not orbitinghail/sqlsync (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "lib/sqlsync/Cargo.toml" \\
  && ok "lib/sqlsync/Cargo.toml" \\
  || miss "missing critical file: lib/sqlsync/Cargo.toml"
test -f "lib/sqlsync-reducer/src/lib.rs" \\
  && ok "lib/sqlsync-reducer/src/lib.rs" \\
  || miss "missing critical file: lib/sqlsync-reducer/src/lib.rs"
test -f "lib/sqlsync-worker/sqlsync-wasm/Cargo.toml" \\
  && ok "lib/sqlsync-worker/sqlsync-wasm/Cargo.toml" \\
  || miss "missing critical file: lib/sqlsync-worker/sqlsync-wasm/Cargo.toml"
test -f "demo/cloudflare-backend/src/coordinator.rs" \\
  && ok "demo/cloudflare-backend/src/coordinator.rs" \\
  || miss "missing critical file: demo/cloudflare-backend/src/coordinator.rs"
test -f "lib/sqlsync-react/src/context.tsx" \\
  && ok "lib/sqlsync-react/src/context.tsx" \\
  || miss "missing critical file: lib/sqlsync-react/src/context.tsx"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 199 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~169d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/orbitinghail/sqlsync"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

SQLSync is a collaborative offline-first wrapper around SQLite that synchronizes state across users, devices, and edge environments using eventual consistency. It enables web applications to perform optimistic reads/writes on SQLite with real-time multi-user collaboration, cross-tab sync, and reactive query subscriptions—designed for use cases like Figma-style document editing or edge deployments with poor connectivity. Monorepo (Cargo workspace with resolver 2.0) organized as: lib/sqlsync (core engine), lib/sqlsync-worker/sqlsync-wasm (WASM bindings), lib/sqlsync-reducer (stateless compute), lib/sqlite-vfs (virtual filesystem), demo/cloudflare-backend (edge coordinator), demo/frontend (React + TypeScript UI), and examples/reducer-guestbook (reference implementation). The frontend uses Vite/React with vanilla JS and TypeScript.

👥Who it's for

Web developers and product engineers building collaborative applications (especially React-based) who want local-first SQLite databases that automatically sync between browser tabs, devices, and backend services without managing complex state management or sync logic themselves.

🌱Maturity & risk

Actively maintained as of v0.3.2 with working CI/CD in .github/workflows/actions.yaml, functioning demo app, and Discord community. The codebase is beyond proof-of-concept (231KB Rust, multiple working packages) but is pre-1.0, suggesting the API and sync guarantees are still evolving. Production-ready for collaborative offline-first use cases, but the ecosystem is still building out.

Moderate risk: the project depends on a forked rusqlite (custom branch for WASM support at rev = 504eff51...), a custom fork of gloo for WebSocket/WASM fixes, and a pinned git revision of tsify. These forks introduce maintenance burden and potential supply-chain fragility if upstream diverges. Single primary author listed (Carl Sverre) increases bus-factor risk; no indication of issue backlog size or response time.

Active areas of work

The project is at v0.3.2 with active CI on main. The demo todo app is deployed and live (sqlsync-todo.pages.dev). Recent focus appears to be on Cloudflare Workers integration (dedicated demo backend), React library polish, and cross-tab synchronization via shared workers. No breaking changes visible in CHANGELOG beyond normal iteration.

🚀Get running

git clone https://github.com/orbitinghail/sqlsync.git
cd sqlsync
cargo build
# For demo frontend:
cd demo/frontend
npm install
npm run dev

Daily commands: Dev frontend: cd demo/frontend && npm install && npm run dev (Vite dev server, typically http://localhost:5173). Backend coordinator: cd demo/cloudflare-backend && wrangler dev. Monorepo: cargo build --workspace or cargo test --workspace.

🗺️Map of the codebase

  • lib/sqlsync/Cargo.toml — Root workspace member defining the core SQLSync library—all collaborators must understand the primary crate's dependencies and feature flags
  • lib/sqlsync-reducer/src/lib.rs — Core reducer FFI that bridges host and guest WASM modules; essential for understanding state synchronization and mutation application
  • lib/sqlsync-worker/sqlsync-wasm/Cargo.toml — WASM worker entry point defining the compilation target and JS bindings; critical for understanding browser-side architecture
  • demo/cloudflare-backend/src/coordinator.rs — Coordinator implementation showing the backend synchronization strategy; demonstrates how SQLSync orchestrates multi-client consistency
  • lib/sqlsync-react/src/context.tsx — React context provider wrapping SQLSync state; primary integration point for web applications and exemplar of the public API
  • README.md — High-level overview of SQLSync's design goals (offline-first, collaborative, edge-ready) and must be read first for context
  • GUIDE.md — Comprehensive contributor guide covering architecture patterns, reducer design, and development workflow

🛠️How to make changes

Add a new reducer mutation handler

  1. Define a new mutation type in your reducer's Rust code (e.g., in examples/reducer-guestbook/src/lib.rs), implementing any validation or side-effect logic (examples/reducer-guestbook/src/lib.rs)
  2. Update the types module to add serialization support for your new mutation if needed (lib/sqlsync-reducer/src/types.rs)
  3. Export the reducer via the guest FFI or host FFI wrapper so clients can invoke it (lib/sqlsync-reducer/src/guest_ffi.rs)
  4. Call the new mutation from your React component using the useMutation hook after importing it from sqlsync-react (lib/sqlsync-react/src/hooks.ts)

Create a new collaborative application using SQLSync + React

  1. Create a new directory in examples/ and set up a package.json with vite + typescript based on examples/guestbook-react/package.json (examples/guestbook-react/package.json)
  2. Wrap your app with SQLSyncProvider from sqlsync-react context and initialize a database connection (lib/sqlsync-react/src/context.tsx)
  3. Write SQL schemas and define your reducer mutations in a Rust crate (reference demo/demo-reducer/src/lib.rs for structure) (demo/demo-reducer/src/lib.rs)
  4. Build your frontend components using useQuery and useMutation hooks to read and mutate state (lib/sqlsync-react/src/hooks.ts)
  5. Deploy a backend coordinator (reference demo/cloudflare-backend/src/coordinator.rs) to order mutations across clients (demo/cloudflare-backend/src/coordinator.rs)

Deploy a SQLSync coordinator backend to Cloudflare Workers

  1. Create a new wrangler.toml configuration with Durable Objects or KV namespace bindings (demo/cloudflare-backend/wrangler.toml)
  2. Implement the coordinator logic to receive mutations, apply ordering, and broadcast to clients (demo/cloudflare-backend/src/coordinator.rs)
  3. Implement persistence to durably log mutations using Durable Objects or another backend (demo/cloudflare-backend/src/persistence.rs)
  4. Export a fetch handler that routes mutations and synchronization messages (demo/cloudflare-backend/src/lib.rs)

Debug or extend the WASM-to-JavaScript bindings

  1. Review the guest FFI (WASM side) to understand what functions are exported to JavaScript (lib/sqlsync-reducer/src/guest_ffi.rs)
  2. Check the host FFI (JavaScript side) to see how those functions are called and what types are marshalled (lib/sqlsync-reducer/src/host_ffi.rs)
  3. If adding new state or operations, update the types module to support serialization (lib/sqlsync-reducer/src/types.rs)
  4. Rebuild the WASM module and test in a demo or example application (lib/sqlsync-react/src/context.tsx shows integration) (lib/sqlsync-worker/sqlsync-wasm/Cargo.toml)

🔧Why these technologies

  • Rust + WASM — Enables high-performance synchronization engine in the browser with memory safety and small binary footprint; shared code between server (via Cloudflare Workers) and client
  • SQLite — Provides ACID semantics, SQL query interface, and embedded database for local-first state; avoids external dependencies for data persistence
  • React/Solid.js bindings — Integrates SQLSync into popular UI frameworks without requiring application-level awareness of synchronization complexity
  • Cloudflare Workers + Durable Objects — Provides edge-deployed coordinator and durable operation log at global scale with minimal infrastructure management
  • Reducer pattern (guest/host FFI) — Separates user-defined business logic (Rust reducer) from synchronization engine, enabling composable validation and conflict resolution

⚖️Trade-offs already made

  • WASM module boundary requires serialization overhead for all mutations
    • Why: Isolation between JavaScript and Rust code enforces safety and prevents accidental shared state corruption
    • Consequence: Bincode serialization adds latency (~microseconds) per mutation;

🪤Traps & gotchas

WASM fork dependencies: The project uses custom branches of rusqlite (WASM support) and gloo (Cloudflare websocket fixes)—these are pinned git revisions, not published crates. If you hit WASM compilation errors, check the fork branches. Single statement rule: The README warns that execute!() only runs one SQL statement at a time; multiple statements in one call will silently fail. Shared worker debugging: By default SQLSync runs in a SharedWorker, making breakpoint debugging tricky—use chrome://inspect/#workers in Chrome. Build targets: The custom libsqlite3-sys feature flags wasm32-unknown-unknown-openbsd-libc, which is non-standard; cargo clean + rebuild if you switch platforms. No dev environment docs: There is no .env.example or setup script; you must manually understand what env vars the Cloudflare backend expects (likely SQLSYNC_* vars based on patterns, but not documented).

🏗️Architecture

💡Concepts to learn

  • Eventually Consistent State — SQLSync's core guarantee is eventual consistency (not strong consistency), meaning mutations arrive out-of-order on different devices but converge to the same state. Understanding this trade-off is critical to designing reducers that tolerate reordered events.
  • CRDT (Conflict-free Replicated Data Type) — SQLSync uses CRDT principles (event log, commutativity, idempotence) to resolve concurrent mutations without a total ordering authority. The reducer engine must produce commutative operations for safety.
  • Optimistic Concurrency — SQLSync performs reads and writes locally before sync confirmation. Mutations are speculatively applied, then reconciled if server state differs. This is why the demo todo app feels responsive offline.
  • SharedWorker API — SQLSync uses browser SharedWorker to run a single database instance across multiple tabs. Understanding this is essential for debugging multi-tab sync behavior and understanding the architecture.
  • WebAssembly (WASM) Modules — The entire sync engine and SQLite runtime are compiled to WASM; reducers are user-defined WASM modules executed by wasmi VM. This determines the performance profile and deployment model.
  • Event Sourcing — SQLSync stores an immutable append-only log of mutations (events) rather than just final state. This log is replayed to reconstruct state and is the basis for sync across devices.
  • Virtual File System (VFS) Layer — The lib/sqlite-vfs crate intercepts SQLite I/O operations to enable WASM-based file storage and custom persistence. This is how SQLite runs in the browser without native filesystem access.
  • electric-sql/electric — Competing offline-first SQLite sync solution; uses Postgres + local SQLite with similar CRDT-style eventual consistency model, good comparison for architecture decisions
  • vlcn-io/cr-sqlite — Conflict-free replicated SQLite using CRDTs; similar problem space but different approach (in-SQLite CRDT columns vs. external sync engine)
  • pouchdb/pouchdb — Predecessor/inspiration for offline-first sync patterns; uses similar replication log concepts but for NoSQL, informs understanding of eventual consistency in SQLSync
  • cloudflare/workers-sdk — Cloudflare Workers tooling required to deploy the demo/cloudflare-backend coordinator; essential for understanding edge deployment patterns in this repo
  • facebook/react — The demo frontend and React library integration depend on React 18; understanding React hooks and component lifecycle is necessary for the client-side integration layer

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add WebSocket reconnection and network resilience tests for sqlsync-wasm

SQLSync is positioned as 'offline-first' with 'high tolerance for unreliable network conditions', but there are no visible tests for connection recovery, message queuing during offline periods, or reconnection scenarios. The gloo-based WebSocket integration in lib/sqlsync-worker/sqlsync-wasm needs test coverage for dropped connections, partial syncs, and backpressure handling.

  • [ ] Create lib/sqlsync-worker/sqlsync-wasm/tests/websocket_resilience.rs with mock WebSocket disconnection scenarios
  • [ ] Test message queue behavior when connection drops (verify queued mutations are replayed)
  • [ ] Add tests for exponential backoff reconnection logic in the coordinator client
  • [ ] Verify that offline state changes don't corrupt the local SQLite database

Add integration tests for the reducer execution and state machine validation

The demo/demo-reducer and lib/sqlsync-reducer modules define critical business logic for applying mutations to SQLite state, but there are no visible integration tests validating that multiple concurrent mutations resolve consistently or that the Wasm reducer produces deterministic output. This is essential for a collaborative system.

  • [ ] Create lib/sqlsync-reducer/tests/concurrent_mutations.rs testing multiple mutations applied in different orders
  • [ ] Add tests verifying idempotency of reducer execution (same mutation applied twice = same state)
  • [ ] Test conflict resolution for concurrent writes to the same row/column
  • [ ] Validate that the demo-reducer's guestbook example produces identical state across instances with same mutation history

Add GitHub Actions workflow for WASM build and browser compatibility testing

The repo includes wasm-bindgen and Cloudflare Workers configuration, but .github/workflows/actions.yaml likely only tests Rust/CLI targets. There's no CI verification that the wasm-pack builds succeed across browsers or that the TypeScript/JavaScript interop (tsify) types are correctly generated and match the frontend examples.

  • [ ] Extend .github/workflows/actions.yaml with a 'WASM Build' job that runs wasm-pack build for lib/sqlsync-worker/sqlsync-wasm
  • [ ] Add a job to verify TypeScript type generation against examples/guestbook-react and examples/guestbook-solid-js (check for tsify output validity)
  • [ ] Add a step to build and validate the Cloudflare Workers demo (demo/cloudflare-backend) with wrangler
  • [ ] Include a smoke test running demo/frontend against the built wasm module to catch runtime binding issues

🌿Good first issues

  • Add integration tests for the cross-tab sync behavior in lib/sqlsync/src/ (file watchers, SharedWorker message passing). The codebase has no explicit test/ directory at root, suggesting test coverage could be expanded. Start by writing a test harness for multi-tab state consistency.
  • Write missing JSDoc/TSDoc comments in demo/frontend/src/components/ (TaskForm.tsx, TaskItem.tsx, TaskList.tsx are component-heavy but lack inline docs). Improve IDE autocomplete and contributor onboarding with type annotations and examples.
  • Create a minimal 'Getting Started' example in examples/ that mirrors reducer-guestbook/ but is simpler (e.g., a counter with only 2 mutations) and add a corresponding README walking through it. The guestbook example is ~200 lines; a 50-line version would lower the barrier for new contributors.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 7dc1af6 — Merge pull request #63 from orbitinghail/dep-updates (carlsverre)
  • 9712616 — fix buffersource error (carlsverre)
  • 5c640c9 — cargo fmt (carlsverre)
  • 5d2d52c — testing locally (carlsverre)
  • 25edfd2 — switch worker to new sqlite backed worker (carlsverre)
  • 9110a7a — pass 2 (carlsverre)
  • 664c186 — pass 1 (carlsverre)
  • e8ad116 — release 0.3.2 (carlsverre)
  • 95c2182 — fixing sourcemaps and import bugs (carlsverre)
  • 89654d3 — more verbose sqlite errors (carlsverre)

🔒Security observations

The SQLSync codebase demonstrates reasonable security practices with Apache 2.0 licensing and organized structure. However, the primary security concern is the reliance on custom forks of key dependencies (rusqlite, gloo, tsify) which introduces maintenance risk and potential vulnerability exposure if patches aren't synchronized from upstream. No hardcoded credentials were detected in the provided file structure. The project should establish a formal dependency management and security monitoring process, particularly for the forked libraries. No obvious injection risks or misconfigurations were identified in the visible file structure, though runtime security analysis of the synchronization protocol and database handling would be recommended.

  • Medium · Dependency on Fork of rusqlite with Custom Patches — Cargo.toml - [workspace.dependencies.rusqlite]. The project uses a custom fork of rusqlite (https://github.com/trevyn/rusqlite) on a non-standard branch (wasm32-unknown-unknown). While this enables WebAssembly support, it introduces maintenance risk and potential security gaps if the fork doesn't receive timely security patches from upstream. Fix: Monitor the fork repository for security updates regularly. Consider contributing the wasm32 support back to the upstream rusqlite project or establish a process to sync security patches from upstream.
  • Medium · Dependency on Custom Fork of gloo Library — Cargo.toml - [workspace.dependencies.gloo]. The project depends on a custom fork of the gloo library (https://github.com/carlsverre/gloo) with specific revisions. Custom forks can lag behind security updates in the main repository. Fix: Establish a security monitoring process for this fork. Track upstream gloo repository for security advisories and merge patches promptly. Consider upstreaming the required changes if possible.
  • Medium · Custom Fork of tsify with Pinned Revision — Cargo.toml - [workspace.dependencies.tsify]. The tsify dependency uses a specific fork revision without a clear upgrade path. This can lead to security vulnerabilities if critical patches are released in upstream. Fix: Document why this specific fork/revision is needed. Establish a process to monitor for security updates and test newer versions regularly.
  • Low · Missing Dependency Version Pinning Strategy — Cargo.toml - [workspace.dependencies]. Several workspace dependencies use flexible version specifications (e.g., '1.0', '0.3') without pinning to specific minor/patch versions. While this allows for bug fixes, it could introduce unexpected behavior changes. Fix: Consider using more restrictive version specifications (e.g., '=1.0.5') for production deployments, or implement regular dependency auditing with cargo audit in CI/CD.
  • Low · No Evidence of Dependency Vulnerability Scanning — .github/workflows/actions.yaml. While the GitHub Actions workflow file exists (.github/workflows/actions.yaml), the provided content doesn't show whether cargo audit or similar dependency scanning is performed. Fix: Add cargo audit and cargo deny checks to the CI/CD pipeline to automatically detect known vulnerabilities in dependencies.
  • Low · LTO and Strip Flags in Release Profile — Cargo.toml - [profile.release]. The release profile uses strip = 'debuginfo' which removes debug symbols. While this reduces binary size, it may impact security investigation and crash diagnostics. Fix: Consider maintaining a separate debug symbols file for production builds to aid in security incident investigation while keeping binary sizes small.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · orbitinghail/sqlsync — RepoPilot