RxDB vs GenosDB: Local-First With a Server, or Peer-First Without One
An honest look at RxDB — its WebRTC replication, its premium storage tiers, and the limits its own docs declare — plus what a database designed peer-first does differently.

Full Stack Developer - dWEB R&D
RxDB is one of the best-engineered local-first databases in JavaScript. It has 23,000 stars, 270,000 downloads a month, and a commit history that does not go quiet. If you are building an offline-capable app that syncs with a backend you already run, it is a genuinely good answer, and this article is not going to pretend otherwise.
But RxDB and GenosDB solve different problems, and the difference is not a feature list — it is where the authority lives. RxDB is a local database that replicates to a server. GenosDB is a peer-to-peer database with no server at all. Everything else in this comparison follows from that single line, including the parts where RxDB wins.
This is an honest walkthrough of what RxDB is, where its own documentation draws the line, and what a peer-first design does differently.
What Is RxDB?
RxDB (Reactive Database) is a local-first NoSQL database for JavaScript. It runs in the browser, Node.js, Electron and React Native, persists through a pluggable storage layer, and exposes documents and queries as RxJS observables. Queries follow MongoDB syntax and documents validate against JSON Schema.
Its real strength is the replication layer. RxDB ships official plugins for HTTP, GraphQL, CouchDB, Firestore, Supabase, Appwrite, MongoDB, NATS, WebSocket and WebRTC. If your data already lives somewhere, RxDB probably has a plugin for it.
It is also honest about itself, which is rare. RxDB publishes a page called Downsides of Local First / Offline First listing its own limitations, including "It only works with small datasets", "Browser storage is not really persistent" and "Realtime is a lie". That page is worth reading regardless of which database you pick.
The Architecture Question
Both databases store data in the browser and both can sync between clients. The difference shows up when you ask a simple question: when two peers disagree, who decides?
In RxDB, the server decides. Replication is a protocol between a client and an endpoint — pull and push handlers talking to something you operate. Conflict handling, authorization and identity are your backend's job, because that is where the trust lives.
In GenosDB there is no such place. Every operation is signed by its author before it leaves the browser, and every peer verifies it independently against a shared set of rules. Authority is not a server — it is a signature. That is the Zero-Trust model, and it is what makes running with no backend at all a coherent design rather than a missing feature.
RxDB GenosDB
Browser ──► RxStorage Browser ──► Security Manager (signs)
│ │
└──► replication plugin └──► Graph Store (OPFS)
│ │
▼ ├──► Peers (GenosRTC / WebRTC)
Your backend │
(authority) └──► Nostr relays (discovery only)
Where RxDB Draws the Line — In Its Own Words
RxDB does have a WebRTC replication plugin, so "RxDB can do P2P too" is technically true. The interesting part is what their documentation says about it.
You must operate a signaling server
From the official WebRTC replication docs:
"RxDB ships with a default signaling server (…) This server is made for demonstration purposes and tryouts. It is not reliable and might be offline at any time. In production you must always use your own signaling server instead!"
So the serverless setup has a server in it. You deploy it, you keep it up, you pay for it, and you add authentication to it — their docs say as much: "in production, you'd want to create a more robust signaling server with authentication and additional logic".
GenosDB does not have a signaling server to operate, because peer discovery runs over the Nostr relay network — public infrastructure that already exists, is already decentralized, and never sees your data. If you want your own, GenosSIG runs an ephemeral relay on Cloudflare's free plan. Neither option is a server you maintain.
It is not a full mesh, and they say so
Also from their docs:
"Notice that the peers still have to find each other through a signaling server, so this is not a full offline mesh."
That sentence is followed by a pointer to a different product (Ditto) for environments with no infrastructure at all.
OPFS and encryption are paid features
This is the part most comparisons miss. RxDB's core is Apache 2.0 and free. But on the pricing page, the free tier is capped at 13 open collections in parallel, and these sit behind Pro, from $99/month billed annually:
| RxDB Pro feature | GenosDB |
|---|---|
| RxStorage OPFS | Default storage, free |
| WebCrypto Encryption | Built in, free |
| RxStorage IndexedDB | — (OPFS by default) |
| Fulltext search | $text operator, free |
| Worker / Sharding (Pro Plus, $239/mo) | Worker architecture, free |
OPFS — the storage engine that makes browser persistence fast — costs $1,188 a year in RxDB. In GenosDB it is what you get when you run npm i genosdb, because the production bundle is free for personal and commercial use, with no tiers, no collection caps and no feature gates. The source is proprietary, which is a deliberate governance choice and is stated plainly — GenosDB is not open source, and calling it that would be inaccurate.
Permissions and authentication
RxDB lists this among its own downsides, and the reasoning is sound: in a local-first app the client holds the data, so enforcing who may read or write it is not something the client can be trusted to do. Their answer is the backend.
GenosDB's answer is cryptography. The Security Manager provides WebAuthn-based authentication, role-based access control, ACLs at node level and rule-based governance for promotion and demotion. A peer that receives an unsigned or unauthorized operation rejects it — not because a server said no, but because the signature does not check out.
This is the one axis where the difference is not a trade-off but a genuine capability gap, and it is why GenosDB can claim zero-trust and RxDB does not.
What Peer-First Buys You
Cellular Mesh instead of full mesh
A naive WebRTC mesh opens a connection between every pair of peers: n(n−1)/2 links, which collapses somewhere around 50–100 peers. Cellular Mesh partitions peers into cells with bridges between them, turning quadratic growth into something that scales linearly. This is handled by GenosRTC, GenosDB's own networking layer, with epoch-sealed topology so cell membership cannot be gamed mid-flight.
Hybrid Logical Clocks instead of wall clocks
Conflict resolution based on Date.now() breaks when device clocks drift, which they always do. GenosDB uses Hybrid Logical Clocks — causality without requiring synchronized time.
An operation log, so sync sends deltas
Because every write goes through an oplog, a reconnecting device receives only what it missed. Real numbers from a user's app: a device joining a 210-item space went from 83 KB to 7.9 KB of sync traffic after the Hybrid Delta Protocol landed.
Encryption that does not re-derive a key per node
Version 0.28 replaced per-node PBKDF2 derivation (100,000 iterations, once per node, on every read and write) with a record format where each record carries its own wrapped key. Measured on the same machine and the same data:
| Operation | Before | After |
|---|---|---|
| Read, per node | 10.9 ms | 1.2 ms |
| Write, per node | 11.1 ms | 1.5 ms |
sm.map over 40 encrypted nodes |
~1,790 ms | ~50 ms |
That last row is a 35× improvement, and it came from a public discussion with a developer who hit the problem in a real app.
Zero runtime dependencies
GenosDB ships with none. No transitive tree, no supply-chain surface to audit, nothing to patch when an upstream package is abandoned. That is not a small claim in 2026 — see GunDB's supply chain for what the alternative looks like.
Side by Side
| RxDB | GenosDB | |
|---|---|---|
| Model | Local-first, replicates to a backend | Peer-to-peer, no backend |
| Data model | Documents + JSON Schema | Graph, schemaless |
| Authority | Your server | Cryptographic signature per operation |
| Signaling | Your own server, required in production | Nostr relays (public) or GenosSIG |
| P2P topology | Full mesh via plugin | Cellular Mesh, native |
| Conflict resolution | Custom handlers | Hybrid Logical Clocks |
| Storage | Dexie free · OPFS from $99/mo | OPFS, free |
| Encryption | Pro tier | Built in, free |
| Access control | Your backend | RBAC + ACLs + governance, in the client |
| Collections (free tier) | 13 in parallel | Unlimited |
| Runtime dependencies | Several | Zero |
| Source | Apache 2.0 core, commercial plugins | Proprietary source, free bundle |
| Schema migrations | Required | None |
The Same App, Both Ways
A shared list that syncs live between browsers. Nothing exotic — the "hello world" of collaborative apps.
RxDB, following their own documentation:
import { createRxDatabase } from 'rxdb'
import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie'
import { replicateWebRTC, getConnectionHandlerSimplePeer } from 'rxdb/plugins/replication-webrtc'
const db = await createRxDatabase({
name: 'notes',
storage: getRxStorageDexie() // OPFS storage is a Pro feature
})
await db.addCollections({
notes: {
schema: {
version: 0,
primaryKey: 'id',
type: 'object',
properties: {
id: { type: 'string', maxLength: 100 },
text: { type: 'string' },
at: { type: 'number' }
},
required: ['id', 'text']
}
}
})
const pool = await replicateWebRTC({
collection: db.notes,
topic: 'my-app-notes-room',
connectionHandlerCreator: getConnectionHandlerSimplePeer({
// "You can use the server provided by RxDB for tryouts,
// but in production you should use your own server instead."
signalingServerUrl: 'wss://signaling.rxdb.info/'
}),
pull: {},
push: {}
})
pool.error$.subscribe(err => console.error('WebRTC Error:', err))
await db.notes.insert({ id: crypto.randomUUID(), text: 'hello', at: Date.now() })
db.notes.find().$.subscribe(render)
GenosDB:
import { gdb } from 'genosdb'
const db = await gdb('my-app-notes-room', { rtc: true })
await db.put({ text: 'hello', at: Date.now() })
db.map({ order: 'desc' }, ({ id, value, action }) => render(id, value, action))
No schema to declare, no migration path to maintain, no storage plugin to license, and no signaling server to deploy — peer discovery is already handled over Nostr relays.
To be fair to RxDB: that schema is not only ceremony. It buys validation, typed documents and a migration system, and if your data has a fixed shape enforced across a team, you may want exactly that. The question is whether you are paying for it in a project that does not need it.
What This Looks Like Running
The claim "no backend" is easy to make and easy to check. Every one of these runs entirely in the browser, with nothing deployed behind it.
Collaborative editing without a CRDT library — a block editor where two browsers edit the same document live:

dCode — a code editor with branches, commits and pull requests, peer-to-peer:

A Hacker News clone where moderation is a signed constitution rather than an admin panel:

A collaborative whiteboard, in a single file:

There are more of them — kanban boards, expense splitters, chat, file transfer, audio and video streaming, a Godot multiplayer plugin, and a WebGPU planet with no backend. The point of publishing so many is that "serverless" should be demonstrable, not asserted.
When RxDB Is the Right Choice
I would rather be useful than win an argument, so:
- You already have a backend. If Postgres, Supabase, Firestore or CouchDB is your source of truth and you want offline capability on top, RxDB is built exactly for that and GenosDB is not.
- You need schemas and validation enforced. RxDB's JSON Schema layer catches bad data at the boundary. GenosDB is schemaless by design.
- You need server-enforced authorization. GenosDB verifies cryptographically at every peer, but there is no central authority to appeal to. For some compliance requirements, that is the wrong shape.
- Your dataset is too large for a full replica per browser. Both have this limit; RxDB's storage tiers give you more room to negotiate it.
- You want an open-source core. RxDB's is Apache 2.0. GenosDB's source is not public, and no amount of free licensing changes that.
And in return, GenosDB is the better fit when there is genuinely nothing behind the app: real-time collaboration with no backend to run, offline-first apps where each device holds a full replica, multiplayer browser games, or any product whose cost model cannot survive a per-seat sync bill.
A Note on Where This Comes From
I have spent years inside browser P2P databases. I built the official GUN documentation platform and contributed to that codebase before starting GenosDB, and the design decisions described here — OPFS instead of localStorage, HLC instead of wall clocks, an oplog for delta sync, signatures instead of a trusted server — all came from hitting those specific walls in real projects, not from a whiteboard.
RxDB is not the enemy in that story. It is a well-run project solving a different problem, by a maintainer who documents his own limitations in public, which I respect and have tried to match here. If anything in this comparison is out of date or wrong, tell me and I will correct it — GitHub Discussions is open and I answer.
⭐ Found this useful? Star GenosDB on GitHub — or spin it up in seconds: npm i genosdb.
This article is part of the official documentation of GenosDB (GDB). GenosDB is a distributed, modular, peer-to-peer graph database built with a Zero-Trust Security Model, created by Esteban Fuster Pozzi (estebanrfp).
📄 Whitepaper | overview of GenosDB design and architecture
🛠 Roadmap | planned features and future updates
💡 Examples | code snippets and usage demos
📖 Documentation | full reference guide
🔍 API Reference | detailed API methods
💬 GitHub Discussions | community questions and feedback
🗂 Repository | Minified production-ready files
📦 Install via npm | quick setup instructions

