Hacker News new | past | comments | ask | show | jobs | submit | aboodman's comments login

Hey HN, I just presented this at React Miami and thought you might be interested. I built an app with three upcoming sync engines, and they run side-by-side and interoperate. Happy to answer any questions.

The code is also publicly available here:

https://github.com/rocicorp/syncban


When you say “rebase” what do you mean exactly? Is it the application replaying the transaction including the interactive code, or is it the database writing the same rows/pages that were written last time?


SQLite has an experimental change, "BEGIN CONCURRENT", which uses optimistic locking to allow concurrent non-overlapping writes: https://www.sqlite.org/src/doc/begin-concurrent/doc/begin_co...

So the "rebase" could be the exact same pages (no compute) if none of the writes overlap. If they do, you'd likely need to replay the transaction and make new pages (some compute).


Yes, this is a central issue in sync. For most applications, sync engines just aren't useful without some solution. Of course you need to validate inputs, support fine-grained permissions, etc., as developers have done with web apps for eons.

In Replicache, we addressed this by making your application server responsible for writes:

https://doc.replicache.dev/concepts/how-it-works

By doing this, your server can implement any validation it wants. It can also interact with external systems, do notifications, etc. Anything you can do with a traditional API.

In our new sync engine, Zero (https://zerosync.dev), we're adding this same ability soon (like this week) under the name custom mutators:

https://bugs.rocicorp.dev/issue/3045

This has been a hard project, but is really critical to use sync engines for anything serious.


Happy user of Replicache. You and the team got it right.



I've been very curious about electric -- the idea of giving your application a replicated subset of your databse, using your api as a proxy, is quite interesting for apps where the business layer between the db and the client is thin (our case).

edit: Also their decision to make it just one way sync makes a LOT of sense. Write access brings a lot of scary cases, so by making it only read sync eases some of my anxieties. I can still use Rest / RPC for updating the data


Convex I didnt know yet - looks really crisp (even has svelte support) ! Do you have experience with it? Does it support (decentralized) E2E?


No, Convex is a client/server system like zero, electric, instant, powersync.

If you want a fully decentralized system, check out jazz. It is the best of these currently IMO.


Yeah, my question was more about E2E, optionally decentralised.

Did you use Convex, what's your general experience?


Zero (zerosync.dev) uses transactional conflict resolution, which is what our prior product Replicache and Reflect both used. It is very similar to what multiplayer games have done for decades.

It is described here:

https://rocicorp.dev/blog/ready-player-two

It works really well and we and our customers have found it to be quite general.

It allows you to run an arbitrary transaction on the sever side to decide what to do in case of conflicts. It is the software equivalent of git asking the user what to do. Zero asks your code what to do.

But it asks it in the form of the question "please run the function named x with these inputs on the current backend db state". Which is a much more ergonomic way to ask it than "please do a 3-way merge between these three states".

Conflict resolution is not the reason why there has not been a general-purpose sync engine. None of our customers have ~ever complained about conflict resolution.

The reason there has not been a general-purpose sync engine is actually on the read side:

  - Previous sync engines really want you to sync all data. This is impractical for most apps.

  - Previous sync engines do not have practical approaches to permissions.
These problems are being solved in next generation of sync engines.

For more on this, I talk about it some here:

https://www.youtube.com/watch?v=rqOUgqsWvbw


I think with good presence (being able to see what other users are doing) and an app that isn't used offline, conflicts are essentially not a problem. As long as whatever is resolving the conflicts resolves them in a way that doesn't break the app, e.g. making sure there aren't cycles in some multiplayer app with a tree datastructure. Sounds like Zero has the right idea here, I'll build something on it imminently to try it out.


Agree that if you don't have offline support, then conflict resolution is such a minor issue that you can just do "last write wins" and call it a day.


"It is the software equivalent of git asking the user what to do. Zero asks your code what to do."

You are asking the dev what to do. You are _not_ asking the user what to do. This is akin of the git devs baking in a choice into git on what to keep in a merge conflict.

It's hard to trust you guys when you misrepresent like this. I thought long and hard on whether to respond confrontationally like this, but decided you really need to hear the push back on this.


lol wut?

I represented that we ask the dev what to do:

> Zero asks your code what to do

You agree that's what we do:

> You are asking the dev what to do. You are _not_ asking the user what to do.

I get that your actual issue is you don't think that what we do is "the software equivalent of git asking the user what to do". But like, I also said what we do concretely in the same paragraph. It's not like I was trying to hide something. This is a metaphor for how to understand our approach to conflict resolution that works for most developers. Like all metaphors it is not perfect.

FWIW, there is nothing stopping a developer from having this function just save off a forked copy and ask the user what to do. Some developers do this.

Also FWIW, Zero does not allow offline writes specifically because we want to educate people how to properly handle conflicts before we do. I see down-thread this is the majority of your concern.


I assumed you were doing offline support yeah. I've heard a lot about local first development lately, so I guessed this what what you guys are tackling too.

Without offline support AND you're doing real time updating of data, then conflict resolution is not a real world practical concern. Users will be looking at the same data at the same time anyways, so they generally see what data won out in case of a conflict, as they are looking at real time data as they are editing.

IF you had offline support, and for other sync engines that do: There is a real and meaningful difference between a backend dev and an end user of the application choosing what to do in case of a conflict. A backend dev cannot make a general case algorithm that knows that two end users want to keep or throw away in a conflict, because this is completely situational - users could be doing whatever. And if you push the conflict resolution to the end users, then you are asking a lot of those users. They need to be technically inclined and motivated people in order to take the time to understand and resolve the conflict. Like with git users.


> Without offline support AND you're doing real time updating of data, then conflict resolution is not a real world practical concern.

I disagree with this. There are many real-world cases where keywise lww does the wrong thing. The article I linked up-thread covers many of them. Even a simple counter does the wrong thing.

This is where robust conflict resolution really matters in these systems, not the long-time offline case people often ask about.

You need robust conflict resolution to make correct software and maintain invariants in the face of write/write systems.

> A backend dev cannot make a general case algorithm that knows that two end users want to keep or throw away in a conflict, because this is completely situational - users could be doing whatever. And if you push the conflict resolution to the end users, then you are asking a lot of those users. They need to be technically inclined and motivated people in order to take the time to understand and resolve the conflict. Like with git users.

I agree completely. In my opinion the ideal offline-first write/write UI has never been built, but the team at Ink & Switch are closest:

https://www.inkandswitch.com/patchwork/notebook/

I think the perfect UX in many cases is that syncs goes ahead and tries to land the offline writes, but the user has a history UI where they can see what happened. Like how many collaborative apps do today.

But importantly in this UI the app would represent branches and merges. But unlike Git's fine grained branch/merge points, in this UI it would literally represent points where people went offline and made changes.

Users could then go back and recover the version of their data from when they were offline, or compare (probably manually in two tabs) the two different versions of the data and recover.

This does still ask users to compare and resolve conflicts in the worst case, but it is not a blocking operation or one that is final. The more common case is the user will go ahead with the merge and sometimes find some corruption. They can always go back and see what went wrong after the fact and fix. This seems like the right tradeoff to me of making the common case (no conflict) easy and automatic but making the uncommon but scary case at least not dangerous.

There also needs to be clear first-class UX telling users that they're going offline and what will happen when they come online.

I'm looking forward to someday working on this, but it's not what our users ask about most often so we're just disabling offline writes for now.


> Previous sync engines really want you to sync all data

Linear had to do all sorts of shenanigans to be able to sync all data, for orgs with lots of it – there's a talk on that here:

https://www.youtube.com/watch?v=Wo2m3jaJixU&t=1473s


Is Zero based on prolly trees?


No. When we started the project we used prolly trees initially, but we don't need the content addressing feature for Zero and all the hashing was quite expensive. So now we just use a plain immutable b-tree:

https://github.com/rocicorp/mono/tree/main/packages/replicac...


Yep - Notion doc answers your question.


Sure happy to give my point of view.

Top-level response: I think Instant is very cool and I have a lot of respect for that team and their work. I've tried to be accurate below, but I know the instant folks frequent HN so maybe they can chime in too and correct anything I've gotten wrong.

1. Instant is a full database, including the backend. Zero is not - it connects to some separate authoritative backend db. Currently only Postgres is supported, but our intent is to support other DBs like MySQL, Mongo, Cockroach, and in the fullness of time even custom distributed systems. Zero's "BYODB" approach has some advantages:

* You don't have to trust us to build a correct backend database (nothing Zero can do can corrupt your data - it's just a fancy cache)

* If you end up not liking Zero you can easily move to anything else that can run on top of PG.

* You can adopt Zero incrementally in an existing project by just moving features over to Zero one-by-one.

* Any code, library, or project that works with PG likely already works with Zero.

* Zero can coexist with other types of PG users. If some non-Zero client changes PG, Zero clients will see it update live. If Zero clients change PG, other clients will see it when they next read PG.

* You don't have to wait for us to build features. Admin UI? Use any of the great PG ones. Data export? It's just PG. Backups? Triggers? FKs? Constraints? Schemas? Migrations? Use all the normal PG stuff.

On the flip side this is a more complicated way to build the system and some of that complexity does leak out into Zero's DX. We're trying to minimize it as best we can, but Zero can probably never be quite as 'sleek' an experience as Instant.

2. Instant uses a datalog/triple style data model and a custom query system. Zero's data model is just relational data, and it uses a SQL-style query system. In practice the API that instant exposes is very relational-like, but I still think that if you know SQL already there's less to learn with Zero.

3. Zero is based on Incremental View Maintenance. When data that affects a Zero query changes, Zero does only a small amount of work to reflect the change. To my knowledge, Instant doesn't do this and re-runs the query (correct me if I'm wrong here Instant folks). This was a specific design choice in Zero because ...

4. Zero was designed primarily to support 'the linear use case': storing dozens of MB of data client-side and keeping it up to date with permissions and partial sync. We did not want to have to run these huge queries over and over.

5. Zero is very focused on just being a sync engine. Instant appears to be aiming to take on more of the suite of features Firebase offers like login, email, blob storage, etc.

6. Instant already has a SaaS live, Zero doesn't.


I think there are a lot of free hosts that could work?

  - Fly.io has a free tier that has postgres (if you want to debug from your workstation against live pg, which is useful, it's $2/mo for a public IP)
  - Supabase has a free tier (with the caveat that schema changes will resync the replica - which is fine as long as db is smallish)
  - AWS/RDS offers one year free
Those are just off the top of my head. Plus as jitl mentions you can just run the Dockerized pg in any free docker env.


Hello, HN – I'm aaron - CEO and founder of Rocicorp. We build Zero and Replicache. Very happy to answer any questions!


Will replicache be deprecated? Or continue to be developed/supported? E.g. Partial downloads aren't really necessary in our case so Zero isn't really necessary (although it is cool!).


I hesitate to use the word 'deprecated' because it means different things to different people. We'll continue supporting Replicache but won't add new features to it.

Even if you don't think you'll need partial sync our experience is that almost all projects end up needing either it or permissions. Both of which are difficult with Replicache.

And if you don't need either of those, the the query-based programming model of Zero is just a lot more fun.


I just get a blank black page on iOS Safari. What’s suppose to happen?


It's even (often) in company's selfish interest to have regulation so that they aren't forced into a race to the bottom.


Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: