Installation
@nozbe/watermelondb?Use the migration guide instead. It covers everything on this page.
Requirements
| Minimum | |
|---|---|
| React Native | 0.83+, New Architecture (the old / Paper architecture is not supported) |
| iOS | 15.1 (Xcode 15+) |
| Android | minSdk 24 |
| Windows | RNW 0.84 (New Architecture). See Windows |
react-native-nitro-modules | 0.35.2+ (only needed on iOS, Android, and Windows) |
Expo Go is not supported. Use a development build.
React Native (bare)
-
Install the package, the Nitro peer, and the decorators Babel plugin. If the app already depends on
react-native-nitro-modules, leave it out.yarn add nitromelondb react-native-nitro-modulesyarn add --dev @babel/plugin-proposal-decorators -
Enable decorators in
babel.config.js:module.exports = {presets: ['module:@react-native/babel-preset'],plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],} -
Rebuild the native app. Metro reload is not enough.
npx react-native run-ios # runs pod install for younpx react-native run-android
That's it. Autolinking links SQLite on iOS and Android. You don't add Podfile lines, Gradle lines, or MainApplication code, and there is no setup CLI to run.
If you minify with R8 / Proguard, keep this rule:
-keep class com.nitromelondb.** { *; }
Expo
-
Install:
npx expo install nitromelondb react-native-nitro-modulesyarn add --dev @babel/plugin-proposal-decorators -
Enable decorators in
babel.config.js:module.exports = function (api) {api.cache(true)return {presets: ['babel-preset-expo'],plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],}} -
Add the config plugin to
app.json:{"expo": {"plugins": ["nitromelondb"]}} -
Build a development client:
npx expo run:iosnpx expo run:android# or: eas build --profile development
Development builds, EAS Build, and EAS Update all work. See examples/NotesApp for a complete app.
EAS Update: models, queries, schema, and migrations are JS, so they ship over the air. Bumping nitromelondb or react-native-nitro-modules needs a new EAS Build.
Expo on Apple Silicon: No such module 'ExpoModulesCore'
Pass excludeSimArch to the plugin. It excludes arm64 from iOS simulator builds:
{
"expo": {
"plugins": [["nitromelondb", { "excludeSimArch": true }]]
}
}
Expo web
The same nitromelondb/adapters/sqlite import runs SQLite in the browser through wa-sqlite. It runs in a worker and stores data in IndexedDB. No COOP/COEP headers are needed.
Expo web workers need bundle splitting. Expo Router already sets that up. Without Router, install @expo/metro-runtime and load it only on web:
// webRuntime.web.ts
import '@expo/metro-runtime'
// webRuntime.ts is an empty file. index.ts does: import './webRuntime'
If you have a custom metro.config.js, start from Expo's defaults and make sure .wasm is an asset:
const { getDefaultConfig } = require('expo/metro-config')
const config = getDefaultConfig(__dirname)
if (!config.resolver.assetExts.includes('wasm')) {
config.resolver.assetExts.push('wasm')
}
module.exports = config
Before a release, run npx expo export -p web and check that the output has a worker bundle and a .wasm file.
To host the worker or WASM yourself (custom CDN or CSP), pass web options:
const adapter = new SQLiteAdapter({
dbName: 'app',
schema,
web: {
wasmUrl: 'https://static.example.com/wa-sqlite-async.wasm',
workerFactory: () => new Worker('/nitromelondb-sqlite-worker.js'),
},
})
Limitations, multi-tab behavior, and SSR notes are in wa-sqlite web adapter.
Web without Expo (Webpack, Vite)
Install the Babel plugins:
yarn add --dev @babel/plugin-proposal-decorators @babel/plugin-transform-class-properties
Use this Babel config. Decorators must come first, and class properties must use loose mode:
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-transform-class-properties", { "loose": true }]
]
}
-
Webpack: put it in
.babelrc/babel.config.js. -
Vite + React: pass it to
@vitejs/plugin-react:import { defineConfig } from 'vite'import react from '@vitejs/plugin-react'export default defineConfig({plugins: [react({babel: {plugins: [['@babel/plugin-proposal-decorators', { legacy: true }],['@babel/plugin-transform-class-properties', { loose: true }],],},}),],})
Then pick an adapter in Setup: SQLite (wa-sqlite) or LokiJS.
Windows
NitromelonDB runs on React Native Windows 0.84 (New Architecture / WinAppSDK). It uses the same Nitro engine as iOS and Android. The example app is examples/NotesApp_windows.
You need Node 22.11+, Visual Studio 2022 or 2026 with the C++ and Windows App SDK workloads, and Windows SDK 10.0.26100. If something is missing, run RNW's dependency script.
-
Install the packages and set up Babel the same way as React Native (bare).
-
react-native-nitro-moduleshas no Windows project (nitro#168), so tell RNW autolinking to skip it. In the app'sreact-native.config.js:const { windowsAppDependencies } = require('nitromelondb/windows-autolink')module.exports = {// ...existing project.windows...dependencies: windowsAppDependencies(),}In a monorepo that links NitromelonDB with
file:, pass{ root: path.resolve(__dirname, '../path-to-nitromelondb') }. -
Build:
yarn react-native run-windows
Only direct debugging works (no Remote JS Debugging). How the Nitro install works on Windows: native/windows/README.md.
Node.js and Electron
Install the better-sqlite3 peer:
yarn add better-sqlite3
On Electron, rebuild it against Electron's Node version. Electron Forge does this for production builds, but not in development:
npx electron-rebuild -f -w better-sqlite3
Electron runs SQLite in the main process. See Setup — Electron.
Troubleshooting
Yarn or npm fails to install wa-sqlite
Releases after 0.31.0 don't depend on wa-sqlite at all: the files the web adapter needs ship inside nitromelondb. Upgrading is the simplest fix.
Versions up to 0.30.1-beta.1 pulled wa-sqlite from a git URL. Yarn Classic fails on that with fatal: not a git repository, and Yarn 4 rejects git dependencies that aren't allowlisted. 0.30.1-beta.2 through 0.31.0 use a tarball URL instead. If you are stuck on an older version, add this to your app's package.json:
{
"resolutions": {
"wa-sqlite": "https://codeload.github.com/rhashimoto/wa-sqlite/tar.gz/2bf1c59d89eb6497535a4217bc62fec68a0bb994"
}
}
With npm, use overrides instead of resolutions.
SQLiteAdapter can't create the native database
Check that react-native-nitro-modules is installed and that you did a full native rebuild. Also check that the New Architecture is on and that you aren't passing { jsi: false }, which throws on iOS and Android.
use_frameworks! on iOS
Avoid it if you can. If you need it (RN Firebase often does), use use_frameworks! :linkage => :static. If the build still fails, force static libraries.
Why does Podfile.lock list React-Core, React-jsi, and other React pods under NitromelonDB?
This is normal for any New Architecture native module. Reanimated, Screens, MMKV, and WatermelonDB itself all show the same entries.
The podspec calls React Native's install_modules_dependencies helper, which adds the full New Architecture dependency set (React-Fabric, ReactCommon, hermes-engine, and so on). CocoaPods records those links in Podfile.lock.
This does not mean React is compiled twice (CocoaPods deduplicates pods), and it does not pin a React version (the podspec has no version constraints on React-* pods).