Top
Best
New

Posted by ndrean 4 days ago

ZeBridge – PostgreSQL replicas on devices, synchronized over NATS(github.com)
29 points | 6 comments
satvikpendem 12 hours ago|
Is this like ElectricSQL which was acquired recently?
ndrean 4 hours ago|
ZeBridge delivers to the client the (PG) enabled tables, replicates the schema locally (SQLite, PGLite, DuckDB tables), seeds them, and handles Postgres supported migrations. Local mutations are optimistic, durably queued (locally) and on (re)connection submitted to Postgres for the authoritative decision, and then CDC are echoed back with a verdict.

ElectricSQL is a Postgres-to-client read synchronization engine. It can operate without a local SQL database: it streams selected data as shapes and the selected rows can be maintained as JS objects or maintained by the dev as materialised into a local database. The reverse flow is implemented by the application and its backend API; libraries can add optimistic updates and offline write handling. Electric then synchronizes the resulting Postgres changes back to clients.

You also have PowerSync: it synchronizes the backend data into a local SQLite database using a schema supplied by the application. By default, records are stored as JSON and exposed through SQL views. It also offers native SQLite storage: managed tables, currently in alpha, are created and migrated automatically, while raw tables require developer-managed creation and migrations. Local writes take effect immediately and enter a durable upload queue. The SDK invokes a developer-provided uploadData() function to send those writes to the application’s backend API, which validates and applies them to Postgres. Authoritative changes then return through PowerSync’s synchronization stream.

In conclusion, ZeBridge is therefore closer to PowerSync in its local database and queued-write model, but the responsibilities differ. ZeBridge delivers server-derived schemas and integrates mutation submission and verdict handling. PowerSync manages local SQLite and the upload queue while the application supplies its client schema and backend write logic. Electric focuses on distributing Postgres changes, leaving client storage and the write path to the surrounding application stack.

satvikpendem 54 minutes ago||
How do you handle syncing? Due to not many good options I resorted to putting a CRDT in my database on client and server side and then running their sync functions on every change but I wish Postgres had integrated CRDTs.
ndrean 6 minutes ago||
[dead]
ndrean 4 days ago|
I built ZeBridge to keep a local database on each device (SQLite, PGlite or DuckDB) in sync with a central PostgreSQL, for apps that must keep working on a bad connection.

It's aimed at B2B operational apps (fleets, depots, field teams), where each customer organisation is a tenant. It isn't built for consumer apps with one tenant per user.

How it works: a bridge written in Zig reads PostgreSQL's logical replication and publishes changes to NATS JetStream, one stream per tenant. Clients seed from snapshots kept in the NATS object store, then follow the stream. Writes made offline wait in a local outbox. When the device reconnects they go to PostgreSQL, which applies your rules (functions, row-level security) and sends back a verdict for each one. PostgreSQL stays the authority; NATS only carries the data.

The same NATS connection also reaches your own services. The live demo uses this to ask a routing service for a truck's route: https://bridge.zebridge.eu/demo (five trucks on a map of 16,173 charge points; open it in two tabs).

Clients: TypeScript (browser and Node), and a native Zig library with a C ABI, wrapped for Swift, Android, React Native, Flutter and Python.

Kinrany 13 hours ago|
The write side on the client can't be transparent, can it?

Otherwise either write persistence is best-effort, writes don't work offline at all, or there is some kind of custom conflict resolution layer that guarantees that all writes will be accepted, like CRDTs

ndrean 5 hours ago||
Right, it isn’t transparent. Unlike a CRDT, not every write is guaranteed to be accepted. Every write is applied locally at once, durably queued, and sent to PostgreSQL when online. The guarantee is that no write is lost, and each one ends with an explicit verdict: accepted, or refused with the reason and rolled back locally.