[HN Gopher] Show HN: SyncKit - Offline-first sync engine (Rust/W...
___________________________________________________________________
Show HN: SyncKit - Offline-first sync engine (Rust/WASM and
TypeScript)
Author : danbitengo
Score : 67 points
Date : 2025-11-27 14:31 UTC (8 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| danbitengo wrote:
| Hey HN, I built SyncKit after shipping two local-first projects
| (RestBolt and Graft) and realizing there's no simple way to add
| cross-device sync.
|
| The problem: Existing solutions are either too complex
| (Automerge/Yjs require learning CRDTs) or too restrictive
| (Firebase isn't truly local-first, Supabase has no offline
| support - issue #357 has been open 4+ years with 350+ upvotes).
|
| SyncKit is the middle ground: simple API, works offline-first,
| self-hostable.
|
| Technical highlights: - TLA+ formal verification: 118,711 states
| checked, caught bugs before implementation - Rust - WASM core
| (48.9KB gzipped) - 700+ tests including 80 chaos tests (zero data
| loss) - Server: Bun/Hono WebSocket (SDK works in any JS runtime)
| - Production-ready: v0.1.0 on npm and Docker Hub
|
| Known limitations (v0.1.0): - LWW only - advanced CRDTs (Text,
| Counter, Set) coming in v0.2.0 - React hooks only - Vue/Svelte
| adapters planned - Reference server is Bun (Node/Deno coming
| v0.3.0)
|
| Happy to answer questions about the CRDT implementation, TLA+
| modeling, or WebSocket architecture.
|
| GitHub: https://github.com/Dancode-188/synckit npm: @synckit-
| js/sdk
| threatofrain wrote:
| TLA+ checked! Whoa!
| danbitengo wrote:
| Thanks! The TLA+ modeling actually caught 3 bugs even before
| I wrote any code. Worth the upfront investment. It's way
| easier to debug a state machine model than distributed sync
| logic.
|
| Happy to share more about the verification approach if you're
| interested!
| JackYoustra wrote:
| VERY interested, are you planning on writing a blog? If so
| I would definitely read that post.
| danbitengo wrote:
| I appreciate the enthusiasm! And yeah, I'm planning to
| start blogging about the build process and some of the
| technical decisions probably after launch week settles
| down. I'll post about it on LinkedIn and in the GitHub
| Discussions when it's live. If you're following either,
| you'll see it!
|
| Thanks for the interest!
| rancar2 wrote:
| Please do in the repo, and thank you for the wonderful
| contribution on multiple fronts. This is very well done
| work and documentation. A few tips to help others discover
| the value on the Readme: Add the key memory benchmark
| (currently just above the acknowledgments) to the top of
| the Readme and link to the rest of the benchmarks on the
| page that you already have (maybe rename it benchmarks.md
| in the process): https://github.com/Dancode-188/synckit/blo
| b/main/docs/guides...
| danbitengo wrote:
| That's a great suggestion. The memory benchmark being
| buried is a fair point. I'll move it up top and create a
| proper benchmarks.md page. Thanks for the detailed
| feedback.
| mkl wrote:
| The ReadMe says "Zero data loss with automatic conflict
| resolution (Last-Write-Wins)", bur doesn't LWW guarantee data
| loss?
| danbitengo wrote:
| See my response to skybrian above. You're both asking the
| same good question about the LWW messaging. Short version:
| system-level guarantees, not user-level concurrent edit
| preservation.
| jmoggr wrote:
| > Automerge/Yjs require learning CRDTs
|
| I've been using Automerge for a while and haven't had to look
| at any CRDTs. To me this looks very similar to Automerge.
|
| Neat project!
| android521 wrote:
| Is support for react native on the roadmap?
| danbitengo wrote:
| Not yet, but it's definitely something I'm considering.
|
| Right now v0.1.0 is React (web) only. I'm planning Vue/Svelte
| for v0.2.0, and React Native could absolutely be v0.3.0 or
| sooner if there's demand.
|
| The nice thing is the core sync engine is Rust - WASM, so it's
| framework-agnostic. The main work is just creating the React
| Native bindings and not rebuilding the sync logic.
|
| Are you working on something with React Native? Curious what
| your offline sync needs are because it'd help me prioritize
| what to build next.
| gagik_co wrote:
| This is impressive! After Realm depreciation I have been trying
| many different offline sync options, they are especially few on
| Dart... Dart-Rust binding generator is pretty great though so
| it's nice this is in Rust. Will keep an eye on this.
| danbitengo wrote:
| Thanks! Yeah, Realm's shift in direction left a gap in the
| offline-first space.
|
| I didn't build Dart bindings yet (Rust - WASM - TypeScript for
| v0.1.0), but since the core is in Rust, Dart bindings via
| dart_rust_bridge are definitely feasible. Would actually be a
| great addition.
|
| Are you actively looking for a Realm replacement for a Dart
| project? Curious what your offline sync requirements are. It
| might help me prioritize Dart support
| satvikpendem wrote:
| I use Loro CRDT, which is written in Rust as well, on my Dart
| apps with flutter_rust_bridge and it works pretty well. For
| syncing I'm using their Loro protocol product although I used
| iroh before. However, the annoying thing about how the CRDT
| libraries work is that they're essentially key value NoSQL
| type storage, not relational. I would love something like
| SQLite or Postgres on both the server and client that can
| sync, which companies like ElectricSQL have, but no Dart
| bindings and also I'd prefer to be in the all Rust ecosystem
| as well as self host.
| rancar2 wrote:
| This is a write up that may be helpful for you:
| https://sqlsync.dev/posts/stop-syncing-everything/
| danbitengo wrote:
| You've hit on the core limitation because SyncKit has the
| same issue. Document/key-value like Loro and Yjs. The
| relational model problem is fundamental to CRDTs. They
| guarantee conflict-free convergence because documents are
| independent, but that breaks with foreign keys and joins.
| Can't have arbitrary SQL queries and guaranteed convergence
| without coordination.
|
| ElectricSQL and PowerSync solve it differently (full SQL
| but weaker offline guarantees). For SyncKit, document-based
| state is an architectural choice, not something v0.2.0 will
| change.
|
| I'm curious to know how you're working around this with
| Loro. Are you building your own query layer or are you
| keeping everything denormalized?
| mike_kamau wrote:
| Good work @danbitengo Is this usable in native Android app
| development?
| danbitengo wrote:
| Thanks! For native Android, not directly yet because v0.1.0 is
| Rust - WASM - TypeScript (web/Node/Deno/Bun).
|
| But since the core sync engine is pure Rust, native Android
| bindings are definitely possible. The main paths would be:
|
| 1. JNI bindings directly from Rust
|
| 2. Or using the existing WASM core with a JVM WASM runtime
|
| Haven't prioritized this yet since v0.1.0 focused on web/JS
| ecosystem, but if there's demand for Android, I could explore
| it. Are you working on something that needs offline sync on
| Android?
| p2hari wrote:
| Always nice to see something in here. Would love to hear what is
| your take on https://www.instantdb.com/?
| danbitengo wrote:
| I haven't tried InstantDB yet, but it looks really interesting.
| Thanks for the pointer! Will definitely check it out.
| skybrian wrote:
| The conflict resolution guide seems quite clear:
|
| https://github.com/Dancode-188/synckit/blob/main/docs/guides...
|
| But I'm a little confused about why it says "Zero data loss with
| automatic conflict resolution" on the top level page and "data
| loss possible" under the disadvantages of last-write-wins
| conflict resolution. It makes sense that you have to start
| somewhere, but to my mind, last-write-wins isn't really conflict
| resolution? What does using this library solve?
|
| I guess it means edits to different fields don't conflict. But if
| it's the same field, it will get clobbered.
| danbitengo wrote:
| You're right that this is confusing.
|
| "Zero data loss" means system-level guarantees (no corruption
| from network failures, crashes, etc), not that concurrent edits
| to the same field are preserved. LWW definitely clobbers one of
| the edits.
|
| What v0.1.0 does give you is field-level granularity (edits to
| different fields don't conflict) and guaranteed convergence
| (all devices reach the same state). But yeah, same field = last
| write wins.
|
| The Rust core already has better CRDTs (Text, Counter, Set)
| that handle concurrent edits properly. They just need to
| exposed in the TypeScript SDK for v0.2.0.
|
| I should clarify this in the docs. Thanks for pointing it out.
| whatever3 wrote:
| Based on the commits(especially the early/foundational ones) this
| seems to be built primarily with Claude, but I don't see that
| mentioned in the README.
| pm wrote:
| When you mentioned offline sync and graft, I mistook you for the
| author of this project:
|
| https://github.com/orbitinghail/graft
|
| However, they're clearly two different projects.
|
| I don't want to take away from the work you've done, as you're
| clearly knowledgeable, but as someone else observed, heavy use of
| AI assistance can be observed in all your public projects. It's
| worth explicitly addressing, especially considering the
| foundational nature of your project: it's not easily replaced if
| it turns out to have to have subtle bugs.
|
| Though I rarely use it myself, I'd like to know, simply because
| I'm curious as to how other engineers have incorporated such
| assistance it into their process.
| kbenson wrote:
| I _think_ I know what this is, but the description is so much in
| its own context I 'm not _sure_. It 's for web-apps that also
| want an offline local version that works and deals with syncing
| the data when online again and either local or remote is updated?
|
| It probably markets and explains itself perfectly find for
| someone in that space and/or looking for this solution, so I'm
| not sure that's actually a problem, but if you also want to stick
| in the mind of someone that sees this and doesn't have any
| _current_ interest, but may stumble into needing a solution like
| this in the future, a few extra words in your initial description
| might help it be understood more quickly and be something
| remembered even if they don 't dive into it. Or maybe it's fine
| and I'm just a bit slow today.
| Tooster wrote:
| I want to create a local first, offline/p2p realtime multiplayer
| prototype app soon with reactive/signal data model and frontend
| agnostic design (considering solidjs/svelte). I'm on a tech
| research stage. How does it compare to rxdb, tinybase and zero
| sync? For reference right now I'm considering tinydb/rxdb.
| dgrcode wrote:
| Some time ago I was looking for a similar solution -offline first
| and easy sync- and was happy to find https://jazz.tools/. There
| are many things in common between these two projects. Just
| mentioning in case you want to check it out.
___________________________________________________________________
(page generated 2025-11-27 23:01 UTC)