Next-generation offline-first local database for React Native and TypeScript (WatermelonDB successor).
License: MIT · Author: Nate Nichols
| Package | Description |
|---|---|
@melon-db/db |
Core schema, AST, adapter contract, runtime engine |
@melon-db/db-sqlite |
SQLite adapter (Bun bun:sqlite + Expo export) |
@melon-db/db-sqlite-native |
Native TurboModule + C++ JSI for RN dev builds |
@melon-db/db-query |
Fluent query builder |
@melon-db/db-query-mango |
Mango-style query compiler |
@melon-db/db-prisma |
Prisma-like local client facade |
@melon-db/db-react |
React hooks and provider |
@melon-db/db-devtools |
Devtools event bridge + React inspector panel |
@melon-db/db-testkit |
Test helpers, fixtures, withTestDatabase |
@melon-db/db-codemods |
WatermelonDB migration codemods and query translator |
@melon-db/sync |
Watermelon-compatible pull/push sync orchestrator |
@melon-db/sync-server |
HTTP reference sync backend for dev and integration tests |
npm install @melon-db/db@alpha @melon-db/db-sqlite@alpha @melon-db/db-react@alphaOr with Bun:
bun add @melon-db/db@alpha @melon-db/db-sqlite@alpha @melon-db/db-react@alphabun install
bun test
bun run typecheck
bun run checkimport { createDatabase, createInMemoryAdapter, createMelonSchema } from '@melon-db/db';
const schema = createMelonSchema({
version: 1,
collections: {
tasks: {
name: 'tasks',
primaryKey: 'id',
fields: { id: { kind: 'string' }, title: { kind: 'string' } },
},
},
});
const db = createDatabase({ schema, adapter: createInMemoryAdapter() });
await db.write(async (tx) => {
await tx.collection('tasks').insert({ id: '1', title: 'Hello' });
});
const tasks = await db.collection('tasks').findMany();bun run demoSee apps/playground-node/src/demo.ts.
bun run dev:rn # Expo Go — apps/playground-rn
bun run dev:rn:dev # Dev build install — apps/playground-rn-dev (prebuild + run:ios)
bun run dev:rn:dev:start # Metro for dev client (after install)Open the app in iOS Simulator or Android emulator. See apps/playground-rn/README.md.
bun run melon-prisma generate --schema=./schema.prisma --out=./generated/melonSee packages/melon-db-prisma/README.md.
bun run bench
bun run bench:compare # Melon vs WatermelonDB (better-sqlite3 parity)See packages/melon-db-sqlite/README.md, /docs/performance-comparison, and /docs/performance-comparison/latest-results for methodology and latest timings.
bun run dev:docsOpen http://localhost:3000 — guides at /docs, live playgrounds, package reference, and API docs. See apps/docs/README.md and the docs phase.
Wire the reactive bridge and inspector panel:
import { createReactiveDevtoolsBridge } from '@melon-db/db-devtools';
import { MelonDevtoolsProvider, MelonDevtoolsPanel } from '@melon-db/db-devtools/react';
const devtools = createReactiveDevtoolsBridge();
const db = createDatabase({ schema, adapter, devtools });See packages/melon-db-devtools/README.md.
Use the compatibility matrix and CLI codemods in @melon-db/db-codemods:
bun run melon-codemod migrate-queries --path=./src
bun run melon-codemod migrate-writes --path=./src
bun run melon-codemod migrate-react --path=./src
bun run melon-codemod migrate-schema --path=./src/models/Task.tsThe runtime query translator converts serializable Watermelon Q clauses to Melon QueryAst. Joins (Q.on) require manual rewrite — see the migration guide. migrate-schema extracts a single Model file to JSON.
bun run postgres:up # Docker Postgres on localhost:5433
bun run demo:sync
bun run demo:sync:http
bun run demo:sync:postgres
bun run sync-server
bun run sync-server:postgresSee packages/melon-sync/README.md, packages/melon-sync-server/README.md, and apps/playground-node/src/sync-demo.ts.
import { synchronize, createMemoryCheckpointStore } from '@melon-db/sync';
const db = createDatabase({ schema, adapter, sync: {} });
await synchronize({
db,
pullChanges: async (args) => /* backend pull */,
pushChanges: async (args) => /* backend push */,
checkpointStore: createMemoryCheckpointStore(),
});- All mutations must run inside
db.write(). - SQLite migrations support add-column and create-table only.
- Relation includes load
belongsToandhasManyvia post-fetch batching (no SQL JOIN shaping). - SQLite
observeQueryuses predicate-aware invalidation and cross-collectionrelationFilters, but top-N membership edge cases still exist.
Living status: /docs/roadmap on the docs site (run bun run dev:docs). Phases 0–34 are shipped; see the docs for full phase history, architecture ADRs, and About.
| Done (Phases 0–34) | Deferred (Phase 35+) |
|---|---|
| Core engine M0–M2 | EAS Build CI |
| SQLite SQL compiler + Bun/Node/Expo adapters | Full multi-file schema codemods |
@melon-db/db-sqlite-native — iOS + Android TurboModule + C++ JSI |
Background sync service |
Predicate-aware SQLite observeQuery + trigger flush / JSI update_hook |
Per-field timestamps / three-way merge |
RN on-device benchmark harness (playground-rn-dev /benchmark) |
SQL SELECT JOIN shaping |
Dual RN path: Expo Go + dev build (/rn, mode: 'auto') |
|
WatermelonDB benchmark comparison (bench:compare, CI) |
|
| Query / Mango / Prisma surfaces + React/sync hooks | getChangedCollections adapter API |
| Schema migrations, relation includes, Q.on filters, devtools + docs site | Sliding window retention (prd-4) |
| Full sync stack (HTTP + Postgres, retry, merge-by-field, custom resolver) | |
@melon-db/db-codemods v1 + v2 |
|
| CI (test, typecheck, biome, bench-smoke, bench-compare, postgres-sync, docs, release-smoke) |
Copyright (c) 2026 Nate Nichols. See LICENSE for the full MIT license text.
Alpha npm packages use dist-tag alpha with no production SLA. See Alpha support policy and RELEASING.md.
Per-package typecheck: bun run typecheck. Adapter parity is enforced by shared vectors in packages/melon-db/__fixtures__/.
