I found another blogpost from turso where they say they offer 3 options on conflict: drop it, rebase it (and hope for no conflict?) and "handle it yourself".
Writing an offline sync isn't hard. Dealing with conflicts is a PITA.
https://turso.tech/blog/introducing-offline-writes-for-turso...
How you reconcile many copies of the same record could depend on time of action, server location, authority level of the user, causality between certain business events, enabled account features, prior phase of the moon, etc.
Whether or not offline sync can even work is very much a domain specific concern. You need to talk to the business about the pros & cons first. For example, they might not like the semantics regarding merchant terminals and offline processing. I can already hear the "what if the terminal never comes back online?" afternoon meeting arising out of that one.
But living inside of those rules (and sometimes just understanding those rules) can be a big ask in some situations, so you have to know what you are doing.
> Local-first architectures allow for fast and responsive applications that are resilient to network failures
So are we talking about apps that can work for days and weeks offline and then sync a lot of data at once, or are we talking about apps that can survive a few seconds glitch in network connectivity? I think that what is promised is the former, but what will make sense in practice is the latter.
In my experience, it can affect the architecture and performance in a significant way. If a client can go offline for an arbitrary period of time, doing a delta sync when they come back online is more tricky, since we need to sync a specific range of operation history (and this needs to be adjusted for specific scope/permissions that the client has access to). If you scale up a system to thousands or millions of clients, having them all do arbitrary range queries doesn't scale well. For this reason I've seen sync engines simply force a client to do a complete re-sync if it "falls behind" with deltas for too long (e.g. more than a day or so.) Maintaining an operation log that is set up and indexed for querying arbitrary ranges of operations (for a specific scope of data) works well.
In general this seems to work only if there's a single offline client that accepts the writes.
With limitations to the data scheme (e.g. have distinct tables per client), it might work with multiple clients. However those would need to be documented and I couldn't see anything in this blog post.
If I build an offline first app using Turso, will my client directly exchange data with the database, without a layer of backend APIs to guarantee data integrity and security? For example, certain db write is only permitted for certain users, but when the db API is exposed, will that cause problems? A concrete example would be a forum where only moderators can remove users and posts. Say if I build an offline first forum, can a hacker hack the database on the filesystem and utilize the syncing feature to propagate the hacked data to the server?
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.
Ex. if I'm doing a document-based app, users can have at it, corrupt their own data all they want.
I honestly cannot wrap my mind around discussions re: SQLite x web dev, perhaps because I've been in mobile dev: but I don't even know what it'd mean to have an "offline-first forum" that syncs state: it's a global object with shared state rendered on the client.
When you set aside the implications introduced by using a hack scenario, a simpler question emerges: How would my clients sync the whole forum back to the cloud? Generally, my inclination is to handwave about users being able to make posts and have it "just work", after all, can't Turo help with simple scenarios like a posts table that has a date column? That makes it virtually conflict free...but my experience is "virtually" bites you, hard.
1. At a database level: Using something like RLS in Postgres
2. At a backend level: The sync engine processes write operations via the backend API, where custom validation and authorization logic can be applied.
3. At a sync engine level: If the sync engine processes the write operations, there can be some kind of authorization layer similar to RLS enforced by the sync engine on the backend.
With Turso, you would want a model that had, for example a db per user and one per group. With the turso model you want to think something closer to sharding by hand for secure write user or group.
I could be wrong on this though. That's just my rough understanding.
What I would really love is a sync engine library that is agnostic of your database.
Haven't really seen one yet.
Most apps have user data that needs to be (partially or fully) shielded from other users. Yet, most local-first libs neglect to explain how to implement this with their libraries, or sometimes it's an obscure page or footnote somewhere in their docs, as if this is just an afterthought...
Perhaps they have RLS type policies that are only modifiable on the server.
Meaning the user has effectively direct access to the underlying local database. Which, if blindly and totally synced, gives the user effectively direct access to the central database.
I'd have thought that in this day and age every developer would know by now the importance of not trusting frontend validation in a web application? your doubt has given me some pause.
> we're working hard on the following features: > > Automatic and manual conflict resolution
As such everything within this thread is conjecture unless otherwise informed by their work.
https://benwilber.github.io/programming/2025/03/31/sqlite-is...
I think a lot of people just don't realize how few resources Postgres or MySQL use, and how fast they are. You can run Apache and MySQL and a scripting language on a tiny little 512 MB memory instance, and serve some decent traffic. It works great.
Wanting to use SQLite and deal with replication is a nightmare. I don't get it. (And I love using SQLite in apps and scripts. But not websites!)
Vanilla SQLite solved multiple writers a long time ago when they introduced WAL in 2010. Does Turso not support this?
Is the issue with foreign keys that they're not enabled by default?
In the example, it shows syncing returning a promise. Is there no way to track the progress of the sync?
libSQL does not support realtime/reactivity features. There have been attempts (by both our team and the community), but we encountered difficulties and ultimately abandoned the idea. I can check with the team for the exact reasons.
However, Limbo (our SQLite rewrite in Rust) will include this feature, though there is no ETA yet. It's currently being discussed here: https://github.com/tursodatabase/limbo/discussions/1149. Please share your thoughts and use cases.
To me it’s more general than that though. The expectation of having reactive behavior comes up everywhere from chat apps to collaborative to even games. Polling and refreshing feels very 90s and ”web page centric” but of course in some cases (say long form blogging or similar) it’s not a concern.
Mentioning this as an example use case is simply untrue, right?
libSQL is our fork of SQLite. It adds new features on top of SQLite, such as vector search, replication, server mode, and more. libSQL is open source (MIT license).
The Turso SaaS platform, which provides hosted databases, is not open source.
Limbo (which will be renamed to Turso in the future) is our Rust rewrite of SQLite. It is also open source (MIT license) - https://github.com/tursodatabase/limbo
Again, opinion. It's core infra, in my opinion at least that should never depend on others or, if the others inevitably screw you over for a few $, you need to be able to move without possibly bankrupting your company.
In fairness though their `libsql::Builder::new_remote_replica` works with the bare `sqld`
What makes you think that? Limbo is MIT licensed and I don't see any CLA on [1].
[1]: https://github.com/tursodatabase/limbo/blob/main/CONTRIBUTIN...
I know it's super lame to regurgitate LLM output in comments, but I found it interesting that Grok was able to infer [2] what I was talking about when I made this accusation on X some months ago, and it absolutely nailed basically everything I had in mind:
---
Q: Why might Adam think Limbo is an example of "EEE" so "brazen" as to resemble Microsoft in the 90s?
A: Adam Rezich's comment suggests that Pekka Enberg's project, Limbo, could be seen as an example of "Embrace, Extend, Extinguish" (EEE) tactics, which were notably used by Microsoft in the 1990s. Here's a breakdown of why Adam might think this:
1. Embrace: Limbo starts by embracing SQLite, a widely used, open-source database engine. By aiming for full compatibility with SQLite, Limbo acknowledges and adopts the existing technology, similar to how Microsoft would integrate or support existing standards or technologies in their products.
2. Extend: Limbo extends SQLite by rewriting it in Rust, adding new features like built-in vector search and asynchronous I/O, which are not part of the original SQLite. This extension phase is where Microsoft historically added proprietary features or extensions to standards, making their versions more appealing or functional in certain ways.
3. Extinguish: Although Limbo hasn't reached this phase yet, the potential for extinguishing could arise if Limbo becomes superior enough to make SQLite less relevant or if it leads to a market shift where SQLite users migrate to Limbo due to its enhanced capabilities. Microsoft in the 90s would often extend standards in such a way that their versions became the de facto standard, overshadowing or making competitors' versions obsolete.
The "brazen" aspect comes from the transparency and public nature of the project. Unlike Microsoft's more secretive and strategic approach in the past, Limbo's development is open, with Enberg sharing his plans and progress publicly. This openness, combined with the ambitious goal of completely rewriting a foundational piece of software like SQLite, might seem bold or even audacious, reminiscent of Microsoft's aggressive market strategies but done in a more transparent and community-driven manner.
---
The only thing Grok didn't mention was the overt emphasis on the “community” aspect of this project, which is being promoted as being strictly, even obviously better than sqlite3's way of doing things. For me personally, sqlite3 not being a “community”-focused project is actually a huge advantage—modern programming “communities”, while being good for building hype and allegiance for one's project, generally result in very unpleasant nth-order social effects which have nothing to do with the quality of software.
[0] https://github.com/tursodatabase/libsql/blob/main/CODE_OF_CO...
Turso Offline Sync is an active-active replication system for distributed SQLite/Turso databases. IIUC, this release adds the capability to sync local writes back to the cloud [3].
[1] https://electric-sql.com [2] https://electric-sql.com/blog/2024/11/21/local-first-with-yo... [3] https://turso.tech/blog/turso-offline-sync-public-beta#what-...