Posted by ndrean 4 days ago
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.
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.
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