Migrating from WatermelonDB
NitromelonDB is a maintained fork of WatermelonDB (@nozbe/watermelondb). Models, schema, queries, writers, sync, LokiJS, and the web adapters are the same API. What changed is the npm package name, native linking, and a few React Native SQLite requirements.
If you are starting a new app, skip this page and go to Installation.
Your existing SQLite files, schema version, migrations, and model classes keep working. This is a library swap, not a data migration.
seedNitromelonDB's seed option (see Database seeding) tracks "did this
already run" with a marker that's new in NitromelonDB and never existed under WatermelonDB. On a
database carried over from WatermelonDB, every configured step looks unapplied and will run --
even though the table may already have real user data. If you add seed as part of this swap,
read the "Where to be careful in production" section there first.
1. Swap the npm package
yarn remove @nozbe/watermelondb
yarn add nitromelondb
# (or with npm:)
npm uninstall @nozbe/watermelondb
npm install nitromelondb
rxjs ^7.8.0 is both a dependency and a peer. The dependency is what yarn add nitromelondb / npm install nitromelondb installs for you. The peer is so Yarn/npm hoist a single copy if the app already has RxJS (two copies break Observable / Subscription types). You do not add it yourself.
On React Native (iOS, Android, and Windows), also add the Nitro peer and rebuild native code — skip this if react-native-nitro-modules is already in the app (do not double-install it):
yarn add react-native-nitro-modules
Use react-native-nitro-modules 0.35.2 or newer. NitromelonDB is built against 0.36.x; a * peer range used to hide ABI mismatches that only show up in Xcode or Gradle.
react-native-nitro-modules is optional for web / Node / Electron. It is required for SQLite on iOS, Android, and Windows.
After the JS swap you still need pod install and a full native rebuild. Metro reload is not enough.
2. Rewrite imports
Replace the old scope in JavaScript/TypeScript source, tests, and Jest mocks — not in leftover native project files (see iOS, Android, and Windows):
| From | To |
|---|---|
@nozbe/watermelondb | nitromelondb |
@nozbe/watermelondb/adapters/sqlite | nitromelondb/adapters/sqlite |
@nozbe/watermelondb/adapters/lokijs | nitromelondb/adapters/lokijs |
@nozbe/watermelondb/decorators | nitromelondb/decorators |
@nozbe/watermelondb/react | nitromelondb/react |
@nozbe/watermelondb/sync | nitromelondb/sync |
@nozbe/watermelondb/Schema/migrations | nitromelondb/Schema/migrations |
@nozbe/watermelondb/utils/common/randomId | nitromelondb/utils/common/randomId |
@nozbe/watermelondb/utils/common/logger | nitromelondb/utils/common/logger |
A project-wide replace of @nozbe/watermelondb → nitromelondb is enough for JS/TS imports. It is not enough for native files.
Leave other @nozbe/* packages alone. simdjson and SQLite are vendored inside NitromelonDB (native/vendor/).
// before
import { Database, Q } from '@nozbe/watermelondb'
import SQLiteAdapter from '@nozbe/watermelondb/adapters/sqlite'
import { field, writer } from '@nozbe/watermelondb/decorators'
import { withObservables } from '@nozbe/watermelondb/react'
import { synchronize } from '@nozbe/watermelondb/sync'
// after
import { Database, Q } from 'nitromelondb'
import SQLiteAdapter from 'nitromelondb/adapters/sqlite'
import { field, writer } from 'nitromelondb/decorators'
import { withObservables } from 'nitromelondb/react'
import { synchronize } from 'nitromelondb/sync'
3. iOS
Autolinking picks up the NitromelonDB pod. Remove any WatermelonDB / simdjson / FMDB lines you added by hand — simdjson is compiled into NitromelonDB from vendored sources. You do not add a pod 'simdjson', pod 'FMDB', or pod 'NitromelonDB' line. FMDB is not used.
# Remove these lines if they are in your Podfile.
# Autolinking provides NitromelonDB. simdjson is compiled into that pod —
# there is no separate simdjson (or FMDB) pod to add.
#
# pod 'WatermelonDB', path: '../node_modules/@nozbe/watermelondb'
# pod 'NitromelonDB', path: '../node_modules/nitromelondb'
# pod 'simdjson', path: '../node_modules/@nozbe/simdjson', modular_headers: true
Then pod install (Expo: npx expo prebuild).
use_frameworks! :linkage => :static (common in RN Firebase apps) is supported. Prefer static linkage if you must use frameworks. See Installation — Bare React Native.
Bridging header (only if you import the native header yourself):
// before
#import <WatermelonDB/WatermelonDB.h>
#import <NitromelonDB/WatermelonDB.h>
// after
#import <NitromelonDB/NitromelonDB.h>
A project-wide path replace will turn node_modules/@nozbe/watermelondb/native/ios/.../SupportingFiles into node_modules/nitromelondb/native/ios/.../SupportingFiles, which is not a public include path. Delete those HEADER_SEARCH_PATHS / SupportingFiles entries from the pbxproj. Autolinking and the podspec set the headers.
Minimum iOS deployment target is 15.1.
4. Android
Nitro autolinks. Delete the old JSI Gradle module — do not retarget it:
include ':watermelondb-jsi'fromandroid/settings.gradleimplementation project(':watermelondb-jsi')fromandroid/app/build.gradleWatermelonDBJSIPackagefromMainApplication
native/android-jsiA string replace of @nozbe/watermelondb → nitromelondb will produce:
project(':watermelondb-jsi').projectDir =
new File(rootProject.projectDir, '../node_modules/nitromelondb/native/android-jsi')
That path does not exist. Remove the whole JSI block. Do not point it at native/android either — that module autolinks.
Do not register WatermelonDBPackage by hand — that is the old architecture. Autolinking is required.
The Android Java package is com.nitromelondb (it used to be com.nozbe.watermelondb). Update any R8 / Proguard keep rule:
-keep class com.nitromelondb.** { *; }
Turbo-sync JSON injection now goes through com.nitromelondb.NitromelonNative.provideSyncJson.
Minimum Android SDK is 24.
5. Windows
RNW New Architecture (0.84 / WinAppSDK) uses Nitro, not the old UWP WMDatabaseBridge JSI installer. Autolinking picks up native/windows.
Add this to the app react-native.config.js so RNW does not look for a react-native-nitro-modules Windows project (nitro#168):
const { windowsAppDependencies } = require('nitromelondb/windows-autolink')
module.exports = {
dependencies: windowsAppDependencies(),
}
6. Expo
The config plugin is optional for bare React Native. Autolinking is what actually links SQLite. On Expo, add the plugin so prebuild keeps the New Architecture on (it rejects "newArchEnabled": false).
You do not need @morrowdigital/watermelondb-expo-plugin (that package wired the old Android JSI module).
yarn remove @morrowdigital/watermelondb-expo-plugin
In app.json / app.config.js, replace it with "nitromelondb":
{
"expo": {
"plugins": ["nitromelondb"]
}
}
Then npx expo prebuild (or let EAS Build do it). Development builds, EAS Build, and EAS Update are supported. Expo Go is not. See Installation — Expo.
7. SQLiteAdapter on React Native
iOS and Android SQLite is Nitro-only. NativeModules interop is gone. The old React Native architecture (Paper / the legacy bridge) is not supported — enable the New Architecture (on by default in React Native 0.87; required on 0.83+ as well).
const adapter = new SQLiteAdapter({
schema,
migrations,
// `{ jsi: false }` throws on iOS/Android. Omit it, or leave `jsi: true`.
onSetUpError: error => {},
})
- Do not pass
{ jsi: false }on React Native. - Web still uses LokiJS (or Node SQLite in Electron/Node).
- Windows New Architecture uses Nitro (same HybridObject as iOS/Android). The UWP JSI installer is removed.
If SQLiteAdapter cannot create a native database, install react-native-nitro-modules and rebuild the app — Metro reload is not enough.