Skip to main content
Version: 0.31.1

Installation

Migrating from @nozbe/watermelondb?

Use the migration guide instead. It covers everything on this page.

Requirements​

Minimum
React Native0.83+, New Architecture (the old / Paper architecture is not supported)
iOS15.1 (Xcode 15+)
AndroidminSdk 24
WindowsRNW 0.84 (New Architecture). See Windows
react-native-nitro-modules0.35.2+ (only needed on iOS, Android, and Windows)

Expo Go is not supported. Use a development build.

React Native (bare)​

  1. 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-modules
    yarn add --dev @babel/plugin-proposal-decorators
  2. Enable decorators in babel.config.js:

    module.exports = {
    presets: ['module:@react-native/babel-preset'],
    plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
    }
  3. Rebuild the native app. Metro reload is not enough.

    npx react-native run-ios # runs pod install for you
    npx 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​

  1. Install:

    npx expo install nitromelondb react-native-nitro-modules
    yarn add --dev @babel/plugin-proposal-decorators
  2. 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 }]],
    }
    }
  3. Add the config plugin to app.json:

    {
    "expo": {
    "plugins": ["nitromelondb"]
    }
    }
  4. Build a development client:

    npx expo run:ios
    npx 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.

  1. Install the packages and set up Babel the same way as React Native (bare).

  2. react-native-nitro-modules has no Windows project (nitro#168), so tell RNW autolinking to skip it. In the app's react-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') }.

  3. 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).

Next steps​

➡️ Set up the database