RippleDB
RippleDB
InternalArchitecture

Package Structure & Dependency Rules

How the monorepo is layered, why store-* vs db-* exists, and the dependency graph we enforce.

This page locks in how we organize RippleDB as a monorepo so the core stays portable and we don’t accidentally couple the system to one runtime, database, or UI framework.

The key split: client vs server persistence

RippleDB has two categories of “backend” implementations that must not be blurred:

  • Client-side local truth: the database the UI reads from, updated transactionally via replication.
    • packages: @rippledb/store-*
  • Server-side persistence: the system that accepts changes and serves cursorable incremental history (and may materialize domain tables).
    • packages: @rippledb/db-*

If the names don’t encode this split, contributors will mix responsibilities and the design will erode.

Layered package set (v0)

Foundation

  • @rippledb/core
    • HLC, tags, Change types, merge/apply helpers (pure logic)

Orchestration (no database drivers)

  • @rippledb/client
    • client sync orchestration (outbox, pull/apply/push), policies, stream handling
  • @rippledb/server
    • server interfaces/helpers for append + cursor pull, policies

Client truth stores

  • @rippledb/store-sqlite
  • @rippledb/store-memory (tests)
  • later: @rippledb/store-indexeddb, etc.

Server persistence

  • @rippledb/db-postgres
  • @rippledb/db-sqlite (dev/tests)
  • later: @rippledb/db-dynamodb, etc.

UI bindings (optional)

  • @rippledb/bind-tanstack-query
    • DbEvent → invalidateQueries, list registry, invalidation coalescing

Dependency graph (must hold)

  • @rippledb/core → depends on nothing (or only tiny pure deps)
  • @rippledb/client, @rippledb/server → depend on @rippledb/core
  • @rippledb/store-* → depend on @rippledb/core (and optionally @rippledb/client interfaces)
  • @rippledb/db-* → depend on @rippledb/core (and optionally @rippledb/server interfaces)
  • @rippledb/bind-* → depends on @rippledb/core types + its UI library; never required by core/client/server

To keep this true over time, we should enforce it with workspace constraints or lint rules.

On this page