quinn.io
quinn.io
Prompt

What is a good database for an offline-first progressive web app with bidirectional sync to a server such that clients write to their local state first and when the client is online, any new changes are pushed and pulled from the server? I would expect the client database as well as the server database and synchronization to be open-sourced and self-hosted.

If you want a fully open-source, self-hostable setup where the client writes locally first and then does bidirectional sync when online, the most straightforward choice is:

Best “end-to-end” fit: PouchDB (client) + Apache CouchDB (server)

  • Client DB: PouchDB runs in the browser (typically backed by IndexedDB).
  • Server DB: CouchDB.
  • Sync: Built-in, multi-master replication designed specifically for offline-first; you sync PouchDB ↔ CouchDB (optionally live/continuous) and handle conflicts via document revisions. (PouchDB)

Why it’s usually the default recommendation

  • It matches your requirements most literally: local writes first, then push/pull when connected, with the database and sync protocol being the core product. (PouchDB)
  • It’s a well-trodden architecture for PWAs.

Tradeoffs

  • You’re adopting a document model (JSON docs, no joins). Complex relational querying takes more planning (Mango queries / views).
  • You need to decide a conflict strategy (e.g., last-write-wins per field, manual merge UI, or domain-specific resolution).

Best if you want to keep “any backend DB”: RxDB (client) + your server endpoints

  • Client DB: RxDB (runs in the browser; can use IndexedDB/OPFS depending on setup).
  • Server DB: Whatever you want (Postgres/Mongo/etc.).
  • Sync: RxDB provides an offline-first “git-like” replication protocol; you implement a small set of server endpoints, with conflict handling primarily on the client side. (RxDB)

Why pick this

  • You get an offline-first local DB and don’t have to adopt CouchDB.
  • Works well when you already have an established backend stack and want to add local-first sync without replacing your server database. (RxDB)

Tradeoffs

  • More engineering on the server side than CouchDB/PouchDB, because you must build/operate the replication-compatible endpoints correctly.

If you want Postgres-first “sync down” (and write through your API): ElectricSQL

  • Server: Electric is an open-source Postgres sync engine that focuses on syncing data out of Postgres (partial replication, delivery). (GitHub)
  • Client: You still use a local store, but writes typically go to your API/Postgres (it’s described as a “read-path” sync engine in its README). (GitHub)

Why pick this

  • Great when Postgres remains the source of truth, but you want fast local reads + reactive UX with controlled subsets of data replicated to clients.

Tradeoffs

  • Not the simplest “true bidirectional replication layer” in the CouchDB sense; you’ll still design the write path.

Close-but-not-fully-open-source: PowerSync

  • Client SDKs are open-source, but the server-side sync service is source-available under the Functional Source License (FSL) (not OSI open-source). (powersync.com)

  • Mentioning only because it’s explicitly positioned for offline/local-first sync and self-hosting exists, but it may not meet your “open-sourced” requirement.


Rule of thumb

  • Want the least moving parts with fully open-source DB + sync: CouchDB + PouchDB.
  • Want local-first but must keep Postgres/Mongo/etc. on the backend: RxDB.
  • Want Postgres-centric partial replication and you’re fine with write-through APIs: ElectricSQL.

If you tell me whether your server-side data model is fundamentally document-shaped or relational, and whether you need fine-grained conflict merges (field-level / CRDT-like) vs simpler resolution, I can narrow it to a single recommended architecture.