Skip to main content

ReactReact Native Database

If you are looking for a React Native Database, you usually want three things:

  1. Persistence: Store data locally on the device so the app works offline.
  2. Reactivity: Automatically update the UI when data changes.
  3. Sync: Replicate data with a backend server in real-time.

RxDB covers all of these requirements out of the box. It is a local-first NoSQL database that runs deeply integrated with React Native, giving you the power of a full featured database engine inside your mobile app.

RxDB

The Storage Layerโ€‹

React Native does not have a native database engine. To store data persistently and efficiently, RxDB offers multiple storage options.

๐Ÿ‘‘ Expo Filesystem (Highest Performance)โ€‹

For the absolute best performance in React Native and Expo applications, the premium Expo Filesystem RxStorage is highly recommended. Built on expo-opfs, it completely bypasses the React Native bridge and delivers significantly faster read/write speeds than traditional SQLite.

SQLiteโ€‹

If you prefer a free solution or specifically need SQLite, RxDB fully supports SQLite. It works on all mobile platforms and abstracts the complex SQL commands into a simple, NoSQL JSON document API.

Depending on your environment, different SQLite adapters are recommended:

For bare React Native projects, use react-native-quick-sqlite. It uses JSI (JavaScript Interface) to communicate directly with C++, effectively bypassing the slow React Native Bridge.

Installation:

npm install rxdb rxjs react-native-quick-sqlite

Configuration:

import { createRxDatabase } from 'rxdb';
import {
    getRxStorageSQLite,
    getSQLiteBasicsQuickSQLite
} from 'rxdb-premium/plugins/storage-sqlite';
import { open } from 'react-native-quick-sqlite';
 
const db = await createRxDatabase({
    name: 'mydatabase',
    storage: getRxStorageSQLite({
        sqliteBasics: getSQLiteBasicsQuickSQLite(open)
    }),
    multiInstance: false,
    ignoreDuplicate: true
});

React Integrationโ€‹

RxDB is deeply integrated with React. It provides hooks that make fetching data and subscribing to changes effortless.

1

1. Provide the Databaseโ€‹

Wrap your application with the RxDatabaseProvider.

import { RxDatabaseProvider } from 'rxdb/plugins/react';
 
export default function App() {
  // ... create db instance
  return (
    <RxDatabaseProvider database={db}>
       <MyComponent />
    </RxDatabaseProvider>
  );
}
2

2. Observe Dataโ€‹

Use the useRxQuery hook (or useLiveRxQuery shortcut) to fetch data. The component will automatically re-render whenever the data in the database changes. You do not have to manage subscriptions or event listeners manually.

import { useRxCollection, useLiveRxQuery } from 'rxdb/plugins/react';
 
function TaskList() {
  const collection = useRxCollection('tasks');
  
  // This hook automatically updates 'tasks' whenever the query result changes
  const { result: tasks } = useLiveRxQuery(
    collection.find({
        selector: {
            done: { $eq: false }
        },
        sort: [{ createdAt: 'asc' }]
    })
  );
 
  return (
    <FlatList
      data={tasks}
      renderItem={({ item }) => <Text>{item.title}</Text>}
      keyExtractor={item => item.id}
    />
  );
}
3

3. Signals (Performance Mode)โ€‹

For high-performance applications with frequent data updates, re-rendering the entire React component might be too slow. RxDB supports Signals (via @preact/signals-react or similar) to pinpoint updates directly to the DOM nodes.

// Enable the signals plugin once
import { addRxPlugin } from 'rxdb';
import {
    RxDBReactivityPreactSignalsPlugin
} from 'rxdb/plugins/reactivity-preact-signals';
addRxPlugin(RxDBReactivityPreactSignalsPlugin);
 
// ... in your component
const signals = collection.find().$$; // Returns a Signal<Doc[]>

Using signals allows you to update only the specific text node that changed, keeping your UI running at 60fps even with massive data flux.

Sync with Backendโ€‹

A local database alone is useful. But most real-world apps also have to sync their data with a backend. RxDB provides a robust replication protocol that can sync with any backend.

It has dedicated plugins for popular backend solutions:

For custom backends, you can implement the simple HTTP replication protocol.

Example: Sync with Supabaseโ€‹

Syncing is set-and-forget. You start the replication, and RxDB handles the rest (pulling changes, pushing writes, handling conflict resolution).

import { replicateSupabase } from 'rxdb/plugins/replication-supabase';
 
const replicationState = replicateSupabase({
    replicationIdentifier: 'my-sync',
    collection: db.tasks,
    supabaseClient: supabase,
    pull: {},
    push: {},
});

Because RxDB handles the sync layer, you can build your app as if it were a purely local application. All reads and writes happen against the local SQLite database instantly, while the replication happens in the background. This is the essence of Local-First development.

Comparison with Alternativesโ€‹

In the following you can see how RxDB compares to the most common React Native storage and database solutions. Each of them has valid use cases. The trouble starts when you use a key-value store for document data or a cloud SDK for an offline-first app.

FeatureAsyncStorageMMKVSQLite (Raw)WatermelonDBRealmFirestore (SDK)RxDB RxDB
TypeKey-Value StoreKey-Value StoreRelational (SQL)ORM on SQLiteObject StoreCloud Document StoreNoSQL Document Store
ReactivityโŒ Noneโš ๏ธ Per-key listenersโŒ Manual eventsโœ… Observablesโœ… Local listenersโœ… Real-time listenersโœ… Hooks / Signals / RxJS
Persistenceโœ… File (Slow)โœ… File (memory-mapped)โœ… File (Generic)โœ… SQLiteโœ… Custom Fileโš ๏ธ Partial Cacheโœ… SQLite / File
SyncโŒ ManualโŒ ManualโŒ Manualโš ๏ธ Client primitives onlyโŒ Shut down 2025โœ… Firebase onlyโœ… Any Backend
Query EngineโŒ NoneโŒ Noneโœ… SQL Stringsโœ… Query builderโœ… Custom APIโœ… Limitedโœ… Mango JSON Query
SchemaโŒ NoneโŒ Noneโœ… SQL Schemaโœ… Schema + Modelsโœ… Class SchemaโŒ Looseโœ… JSON Schema
MigrationโŒ ManualโŒ ManualโŒ Manual SQLโœ… Migration APIโœ… Migration APIโŒ Noneโœ… Automatic

Summaryโ€‹

  • AsyncStorage: Good for simple key-value pairs like settings and flags. On Android it stores everything in one SQLite-backed store with a default total size limit of 6 MB and a read limit of about 2 MB per entry (known limits). Too slow and too limited for document data.
  • MMKV: react-native-mmkv is a fast, synchronous key-value store that uses JSI to skip the React Native bridge. It is a good AsyncStorage replacement for settings. But it is not a database: there are no queries, no indexes, and no sync.
  • SQLite: Great foundation, but requires writing raw SQL and manual reactivity/sync. RxDB uses it as a storage layer instead.
  • WatermelonDB: WatermelonDB is a reactive ORM on top of SQLite, built for large datasets with lazy loading, and it performs well at that job. Its sync feature only ships the client-side primitives, so you have to design and implement the pull/push endpoints on your backend yourself, and the relational schema requires hand-written migrations.
  • Realm: Fast object store, but MongoDB deprecated it in September 2024 and shut down the Device Sync service on September 30, 2025 (deprecation notice, community discussion). The local database lives on as open source, but without sync you should not start new projects on it. The Realm migration guide shows how to move to RxDB.
  • Firestore: Easy networked DB, but poor offline support (cannot start offline), vendor lock-in, and latency issues. RxDB can replicate with Firestore so that reads and writes stay local.
  • RxDB: Combines the performance of local SQLite with the ease of NoSQL, automatic reactivity, and backend-agnostic synchronization.

Performance claims are cheap. You can find measured numbers for the different RxDB storages on the RxStorage performance page, and it is recommended to run your own measurements with the access patterns of your app.

FAQโ€‹

What database should I use for React Native?

For small key-value data like settings, AsyncStorage or MMKV are enough. When your app stores documents, needs queries and indexes, or has to work offline, you have to use a real database. RxDB combines local SQLite persistence with automatic reactivity and replication to any backend, which is why it fits most offline-first React Native apps.

Does RxDB work with Expo?

Yes. RxDB runs in Expo apps with the expo-sqlite adapter of the SQLite RxStorage, and for the best performance you can use the Expo Filesystem RxStorage which bypasses the React Native bridge. Both work with the managed Expo workflow.

Is AsyncStorage a database?

No. AsyncStorage is an unencrypted key-value store without queries, indexes, or schemas. On Android its default total size limit is 6 MB (known limits), so storing your app's documents in it will bite back as soon as the dataset grows. Use it for settings and use a database for data.

What should I use instead of Realm in React Native?

MongoDB deprecated Realm in September 2024 and shut down its Device Sync service on September 30, 2025, so new projects should not be started on it. RxDB is the closest replacement because it is also a local, reactive, object-like database, and its Sync Engine works with your own backend instead of a proprietary cloud. The Realm migration guide describes the migration path.

Can RxDB sync with any backend?

Yes. The RxDB replication protocol is backend-agnostic and only requires you to expose pull and push handlers, for example over the simple HTTP replication. There are also prebuilt plugins for Supabase, Firestore, GraphQL, and CouchDB.


Ready to start? Check out the React Native Example Project or read the Quickstart Guide.