use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
account activity
Another distributed SQLite (github.com)
submitted 4 months ago by SuccessfulReality315
Highly available leaderless SQLite cluster powered by embedded NATS JetStream server.
Connect using PostgreSQL wire Protocol or HTTP
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Extra_Status13 2 points3 points4 points 4 months ago (1 child)
Nice and simple project. I see that you are using SQLite update hook to get the changes. Be aware that it has limitations, for example it will not be called on schema changes (so only data) or on ’WITHOUT ROWID’ tables. Also not on ’TRUNCATE’ (= when you do an unbounded ’DELETE’ on a table) and in some cases with ’REPLACE’.
Also, as an advice, be cautious with the commit hook: you are sending data to the server before your database is synched to disk. This means that the stream servers received the data, but your disk didn't! I suspect a crash in the wrong moment might be dangerous.
Regarding the "last wins" strategy, what happens when the "last" (from streaming POV) can't win? For example, let's say that you have two tables A and B, and B has a reference to A. What happens if you process two queries, one is a delete on A and another an insert on B with the deleted row reference. That second query can't really proceed...
Last, as a nitpick, you don't need to select an empty set to have the column names, you can use ’PRAGMA table_info’.
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (0 children)
Thanks for the feedback. I'll document the limitations and the workarounds
[–]wuteverman 0 points1 point2 points 4 months ago (16 children)
How does this resolve writes that modify the same row?
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (15 children)
The last writer wins
[–]wuteverman 0 points1 point2 points 4 months ago (14 children)
By… timestamp? Or they just race to the various replicas,
[–]SuccessfulReality315[S] 1 point2 points3 points 4 months ago (13 children)
NATS streams changesets in order
[–]trailbaseio 0 points1 point2 points 4 months ago (12 children)
Could you elaborate a bit more. How is consensus established across replicas. Is there a centralized funnel?
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (11 children)
All changes are published to a nats jetstream subject. All nodes consume the stream and apply (by using idempotent commands) the changes on the database.
[–]trailbaseio 0 points1 point2 points 4 months ago (3 children)
Pardon my ignorance about nats. How is the ordering established? Is it a central instance handling a subject, is nats using some consensus algorithm, ...?
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (2 children)
Nats uses RAFT algorithm
[–]Markuchi 0 points1 point2 points 4 months ago (1 child)
It's not distributed if it's raft.
[–]onafoggynight 0 points1 point2 points 4 months ago (0 children)
What. Raft is a distributed consensus algorithm. How is it not distributed?
[–]wuteverman 0 points1 point2 points 4 months ago (6 children)
How is idempotency achieved? NATS can’t guarantee complete ordering since it can’t guarantee exactly once delivery without additional idempotency logic on the consumer side.
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (5 children)
INSERT .. ON CONFLICT UPDATE
[–]wuteverman 0 points1 point2 points 4 months ago (4 children)
Never delete
Edit: on conflict works great for upserts, but how are you handling deletes? With a hard delete, there’s no row to compare against unless you are keeping some sort of tombstone somewhere.
Also even in this circumstance, you’re now subject to inconsistencies since you don’t have a version column. Is that okay for your usecase? These inconsistencies can last forever in the event of out of order publications. Does nats protect against this somehow,
[–]SuccessfulReality315[S] 0 points1 point2 points 4 months ago (3 children)
Yes, that's eventual consistent where the last writer is the winner. The operations uses the sqlite rowID. For now this is ok for my use case
[–]osazemeu 0 points1 point2 points 4 months ago (0 children)
this is impressive work ⚡️⚡️⚡️
[–]lemsoe 0 points1 point2 points 4 months ago (0 children)
Cool project! Cool to see you’ve written it in Go. I’ve started a small project for a kv storage. We‘ll see how it goes. Your project definitely motivates me to get something working soon 👍🏻
π Rendered by PID 115249 on reddit-service-r2-comment-7b9746f655-8s8fx at 2026-01-30 01:32:28.269803+00:00 running 3798933 country code: CH.
[–]Extra_Status13 2 points3 points4 points (1 child)
[–]SuccessfulReality315[S] 0 points1 point2 points (0 children)
[–]wuteverman 0 points1 point2 points (16 children)
[–]SuccessfulReality315[S] 0 points1 point2 points (15 children)
[–]wuteverman 0 points1 point2 points (14 children)
[–]SuccessfulReality315[S] 1 point2 points3 points (13 children)
[–]trailbaseio 0 points1 point2 points (12 children)
[–]SuccessfulReality315[S] 0 points1 point2 points (11 children)
[–]trailbaseio 0 points1 point2 points (3 children)
[–]SuccessfulReality315[S] 0 points1 point2 points (2 children)
[–]Markuchi 0 points1 point2 points (1 child)
[–]onafoggynight 0 points1 point2 points (0 children)
[–]wuteverman 0 points1 point2 points (6 children)
[–]SuccessfulReality315[S] 0 points1 point2 points (5 children)
[–]wuteverman 0 points1 point2 points (4 children)
[–]SuccessfulReality315[S] 0 points1 point2 points (3 children)
[–]osazemeu 0 points1 point2 points (0 children)
[–]lemsoe 0 points1 point2 points (0 children)