← Back to overview
Selection

Boja uses Rocicorp Zero. This document is the full landscape research that led to that decision.

Context: Greenfield "Discord-meets-Skool" — live chat with unbounded history (millions of messages), threads/replies, jump-to-old-message, live streams, role/channel-gated access, courses, multi-server with independent admins, billing/feature gating. Hard requirements: instant resume after offline, near-zero loading screens, native feel on React Native + Web from day one. Current stack: Bun/TypeScript/MongoDB; Postgres is on the table.

Research date: July 2026. Sources: official docs (zero.rocicorp.dev, docs.powersync.com, electric-sql.com, docs.convex.dev, instantdb.com, triplit.dev, docs.livestore.dev, jazz.tools), HN "Offline-First Landscape 2025" thread, 2025 comparison posts, vendor blogs.

The One Framing Question That Matters

Chat history is an unbounded, shared, append-mostly collection. The sync-engine field splits into three architecture families, and only one of them handles this shape natively:

  1. Query-driven partial sync (Zero, PowerSync Sync Streams, InstantDB infinite queries, Triplit): the client subscribes to queries ("last 100 messages in channel X"); anything not covered falls back to the server. This is the correct shape for jump-to-message and infinite history.
  2. Bucket / shape sync (PowerSync legacy Sync Rules, ElectricSQL shapes): the server pre-partitions rows into buckets/shapes; clients sync whole buckets. Works if you can bound bucket size, awkward for arbitrary historical windows.
  3. CRDT document / event-log sync (Jazz, LiveStore, Ditto, Automerge): the unit of sync is a document or event log. Great for collaboration on bounded objects; structurally wrong for a single multi-million-row message table unless you shard aggressively.

A Discord-like app also needs an authoritative server (permissions, moderation, billing, feature gating) — pure local-first data-ownership models fight you here.

1. Rocicorp Zero (zero.rocicorp.dev)

For This App

"Instant resume after offline" fits. Zero itself does not queue a send made while disconnected, so the selected architecture adds a distinct app-owned, message-only durable outbox with authoritative nonce receipts; it does not generalize offline mutations.

2. PowerSync (powersync.com)

3. ElectricSQL (electric-sql.com)

4. Convex (convex.dev)

5. InstantDB (instantdb.com)

6. Triplit (triplit.dev)

Verdict

Architecturally one of the best fits on paper; not a responsible foundation for a venture-scale product in 2026. Watch, don't build.

7. LiveStore (livestore.dev)

8. Jazz (jazz.tools)

9. Brief Evaluations

Replicache (legacy)

Rocicorp's predecessor: client KV store + your push/pull endpoints, per-space versioning; you write the server. Now free/MIT'd and in maintenance; Rocicorp's energy is 100% on Zero. Proven in production (Vercel used it). Fine if you want a battle-tested, DIY-heavy layer today; strategically a dead end — Zero is its successor.

Ditto

CRDT + P2P mesh sync (BLE/WiFi-Direct/LAN), edge-first; huge funding (~$145M, Series B 2023), enterprise pricing, customers = airlines (Alaska), quick-service retail (Chick-fil-A), military. Built for resilient small-data ops at the edge, not consumer-scale fan-out chat with millions of historical rows. Pass, unless offline mesh (festival/venue chat without internet) becomes a differentiator.

WatermelonDB + custom sync

RN-first reactive SQLite ORM with built-in lazy loading and a documented pull/push sync protocol you implement server-side. Web support via LokiJS/IndexedDB is its weak leg; maintenance cadence has slowed. You own: conflict handling, permissions fan-out, partial-sync windowing, jump-to-message. Realistic effort: months of sync-protocol engineering — basically "roll your own" with a nice client ORM.

Roll your own on Postgres logical replication

The Figma/Linear path: WAL → replication consumer → per-user/channel fan-out service → WebSocket + client store (SQLite/IndexedDB) + idempotent write API + rebase logic. Total control, perfect fit… and it is a multi-quarter, senior-team project whose hard parts are exactly what PowerSync/Electric/Zero sell. Only justified if sync is the product moat. Notably, Discord itself is not offline-first — it's server-first with aggressive caching; that's a legitimate architecture too.

Comparison Table

Zero PowerSync ElectricSQL Convex InstantDB Triplit LiveStore Jazz
Sync model Query-driven Streams (query-ish) / buckets Shapes (read-only) Server reactive queries Query subscriptions Query-driven Event-log CRDT CoValues (+partial tables)
Backend DB Postgres PG / Mongo / MySQL Postgres Proprietary Proprietary (OSS) Proprietary (OSS) Event log Proprietary (OSS)
RN maturity Good (newer) Excellent Weak Excellent* Excellent OK Good (Expo) Good
Web persistence IndexedDB (memory-first) SQLite/OPFS PGlite / TanStack DB ❌ in-memory IndexedDB IndexedDB SQLite/OPFS IndexedDB/OPFS
Offline writes ❌ disabled ✅ queued DIY ✅ queued ✅ native ✅ native
Unbounded chat history ★★★ auto server fallback ★★★ on-demand streams + API ★★ shape-per-window ★★★ (server-first pagination) ★★★ infinite queries ★★ ★ full-log sync ★★ unproven
Jump-to-old-message Query falls through to server Subscribe stream / REST New shape / REST Native (server query) Cursor query Query Hard Immature
Permissions ZQL read perms + mutators JWT sync rules + your API Your proxy API TS functions (best) Rule language Rules DIY Crypto groups + new RLS
Server authority on writes ✅ mutators ✅ your API ✅ your API ✅ rules+admin ⚠️ event-sourced ⚠️ CRDT-merge default
Self-host ✅ OSS ✅ (+Cloud $49–599+/mo) ✅ Apache-2 (+Cloud) ⚠️ basic OSS ✅ OSS (+cheap cloud) ✅ only ✅ (+Cloud usage)
Status 2026 GA; 1.0 stable (March 2026) GA, proven GA, proven (reads) GA, well-funded GA-ish, YC ⚠️ company folded v0.4 Early
Abandonment risk Med Low Low-Med Low Med (OSS hedge) High High Med-High

* Convex RN is mature but has no offline persistence.

Postgres vs Mongo Implications

The comparison below is retained as engine-landscape research.

Hybrid Architecture (Historical Comparison; Chosen Boundary Clarified)

The engine-neutral comparison is retained as research. In the selected architecture, physically published hot rows use Zero; archived rows use an authorized read-only HistoryWindow. Archive rows are never promoted into fake Zero entities, and typing/presence remain on the ephemeral WebSocket plane.

Nobody sane syncs millions of messages to a phone. The winning 2026 pattern:

  1. Hot data via sync engine: channel list, membership/roles, unread counts, last N (~100–500) messages per recently active channel. This gives instant resume + zero loading screens.
  2. Cold history via plain server queries: REST/RPC with cursor pagination for scrollback, jump-to-message (fetch window around target), and full-text search. Render the authorized result as a distinct transient history window.
  3. Streams/video: always out-of-band (LiveKit/Mux/etc.); sync engine carries only signaling/metadata.
  4. Billing/feature gating: server-side, in the write path (mutators / upload endpoint / TS functions) + read-permission rules for entitlement-gated channels/courses.

Shortlist for a Discord-Like App

1. Rocicorp Zero — Selected

Query-driven sync with automatic server fallback is the correct primitive for published chat history and jump-to-message; custom mutators fit billing/moderation; zslack proves the shape. Costs identified by the comparison were the Postgres migration, ~100GB published-dataset guidance, and a newer RN/operational path. Zero is now GA/1.0. It still has no disconnected-write queue in the engine itself; the selected architecture mitigates message sends with the app-owned outbox.

2. PowerSync — Safest Bet (Retains MongoDB)

Mature, production-proven, best RN story, true SQLite on all platforms, offline write queue with your Bun API as the authority, Sync Streams give on-demand per-channel windows, sane pricing, self-hostable. Costs: you design stream/bucket boundaries and the write API yourself; the DX is more "infrastructure" than "magic."

3. InstantDB — Fastest to Product

Offline writes, infinite queries, presence/typing built in, permissions language, cheap, OSS hedge. Costs: proprietary data model (leaves Mongo and Postgres), small company, less headroom for exotic server-side logic than raw SQL stacks.

Honorable mention — Convex: if you soften "instant offline resume" to "instant when online, graceful reconnect," its DX, TS server functions and pagination make it the fastest path to a feature-rich community product. It simply isn't offline-first.

Dark horse — ElectricSQL + TanStack DB (+ your Bun write API) if you want maximal control on Postgres with CDN-scalable reads; hold off until RN persistence matures.

Avoid for this use case: Triplit (orphaned), LiveStore (event-log-per-store wrong shape for global chat), Jazz (unproven at this scale, weak default server authority), Ditto (wrong market/pricing), full roll-your-own (only if sync is your moat).

Decision fork, in one line: Keep Mongo & ship safely → PowerSync. Move to Postgres & optimize for the ideal chat UX long-term → Zero (with a REST cold-history layer either way).