name: react-native-mmkv description: Fast synchronous key-value storage for React Native via react-native-mmkv (Nitro-backed). Covers creating and configuring MMKV instances, reading/writing all value types (string, number, boolean, buffer), React hooks for reactive UI, value-change listeners, encryption, AsyncStorage migration, and state-management integrations (zustand, redux-persist, jotai, react-query). Also covers storage limits, multi-process mode, and the V4 upgrade from the class-based API. license: MIT metadata: author: margelo scope: react-native-mmkv tags: react-native, mmkv, storage, key-value, encryption, hooks, zustand, redux, jotai, react-query, async-storage, migration, nitro-modules
react-native-mmkv
A focused reference for AI coding assistants working in a project that uses react-native-mmkv. Answer using the real APIs from this library — not invented ones — by routing to the matching references/*.md file below.
Mental model
react-native-mmkv is a high-performance, synchronous key-value storage library for React Native, backed by Tencent's MMKV C++ engine via Nitro Modules (JSI). It is ~30x faster than AsyncStorage.
The three things that trip people up:
- Everything is synchronous. No
await, no Promises.storage.getString('key')returns the value immediately. This is the whole point — MMKV memory-maps files and reads/writes in-process. - It's a key-value store, not a database. All data is cached in memory. Keep total size under ~100 MB; for larger datasets use react-native-nitro-sqlite or WatermelonDB. There is no fixed storage limit — but memory warnings will fire if you go too large.
- V4 is a breaking rewrite. The constructor changed from
new MMKV()tocreateMMKV(),.delete()became.remove(), andreact-native-nitro-modulesis now a required peer dependency. See the upgrade guide.
V4 requires React Native 0.75+. It works on both the New Architecture and the old architecture (Nitro is backwards compatible).
Routing table — problem to reference
Load the matching file from references/ before writing code. Each reference cites real APIs from the library.
| User is asking about… | Read |
|---|---|
Creating an MMKV instance, configuration options (id, path, encryptionKey, mode, readOnly, compareBeforeSet), the createMMKV() factory |
references/create-instance.md |
Getting/setting values, all data types (string, number, boolean, buffer, objects via JSON), key management (contains, getAllKeys, remove, clearAll), size, trim, importAllFrom |
references/crud-operations.md |
React hooks (useMMKVString, useMMKVNumber, useMMKVBoolean, useMMKVBuffer, useMMKVObject, useMMKV, useMMKVListener, useMMKVKeys), reactive UI |
references/hooks.md |
Listening for value changes outside of React, addOnValueChangedListener, cleaning up listeners |
references/listeners.md |
Encryption (encrypt, decrypt, recrypt), AES-128 vs AES-256, encryptionKey config |
references/encryption.md |
| Migrating from AsyncStorage, data transfer pattern, completion flag | references/migrate-from-async-storage.md |
zustand persist middleware, redux-persist, jotai atomWithMMKV, react-query persister, MobX |
references/state-management.md |
V4 upgrade, breaking changes from V3, new MMKV() → createMMKV(), .delete() → .remove() |
references/upgrade-v4.md |
| Storage size limits, memory warnings, when to use a database instead | references/limits-and-gotchas.md |
If the question doesn't match any row, read references/create-instance.md first — most setup questions start there.
Installation
npm install react-native-mmkv react-native-nitro-modules
cd ios && pod install
Expo:
npx expo install react-native-mmkv react-native-nitro-modules
npx expo prebuild
After install, rebuild the app. No additional native wiring is required.
Quick reference — full MMKV instance API
import { createMMKV, existsMMKV, deleteMMKV } from 'react-native-mmkv'
const storage = createMMKV({ id: 'my-store' })
// Properties (read-only)
storage.id // string
storage.length // number of keys
storage.byteSize // total file size in bytes
storage.size // (deprecated — use byteSize)
storage.isReadOnly // boolean
storage.isEncrypted // boolean
// Write
storage.set('key', 'string' | 42 | true | arrayBuffer)
// Read
storage.getString('key') // string | undefined
storage.getNumber('key') // number | undefined
storage.getBoolean('key') // boolean | undefined
storage.getBuffer('key') // ArrayBuffer | undefined
// Keys
storage.contains('key') // boolean
storage.getAllKeys() // string[]
storage.remove('key') // boolean (NOTE: was .delete() in V3)
storage.clearAll() // void
// Encryption
storage.encrypt('password')
storage.encrypt('password', 'AES-256')
storage.decrypt()
storage.recrypt('newPassword' | undefined) // (deprecated — use encrypt()/decrypt())
// Maintenance
storage.trim() // free unused space
storage.importAllFrom(otherStorage) // returns count imported
// Listeners
const sub = storage.addOnValueChangedListener((key) => { ... })
sub.remove()
// Static helpers
existsMMKV('my-store') // boolean
deleteMMKV('my-store') // boolean
Testing
A mocked MMKV instance is automatically used when testing with Jest or Vitest. Use createMMKV() as normal in tests — no manual mocking needed.
Verifying the skill is loaded
Good test questions:
- "How do I persist zustand state with MMKV?" → should produce a
StateStorageadapter usingstorage.set,storage.getString,storage.remove— not AsyncStorage wrappers. - "How do I migrate from AsyncStorage to MMKV?" → should show the batch-copy pattern with a completion flag, not a drop-in replacement.
- "What's the storage limit?" → should explain there's no fixed limit, but data is memory-mapped so keep it under ~100 MB; use SQLite for larger datasets.
References
| File | Description |
|---|---|
| create-instance.md | createMMKV() factory, all configuration options |
| crud-operations.md | Set/get all types, key management, objects, buffers |
| hooks.md | All React hooks for reactive MMKV usage |
| listeners.md | addOnValueChangedListener, cleanup |
| encryption.md | Encrypt/decrypt instances, AES options |
| migrate-from-async-storage.md | Full migration pattern from AsyncStorage |
| state-management.md | zustand, redux-persist, jotai, react-query, MobX |
| upgrade-v4.md | V3 → V4 breaking changes and migration |
| limits-and-gotchas.md | Storage limits, multi-process, logging, common pitfalls |
Problem → Reference Mapping
| Problem | Reference | Action |
|---|---|---|
| Don't know where to start | create-instance.md | Create instance with createMMKV() |
| Need reactive UI updates | hooks.md | Use useMMKVString / useMMKVObject etc. |
| Encrypting sensitive data | encryption.md | Call storage.encrypt(key) |
| App uses AsyncStorage, want to switch | migrate-from-async-storage.md | Batch migrate then swap calls |
| Zustand/Redux/Jotai persistence | state-management.md | Wire adapter for your state lib |
| Upgrading from V3 to V4 | upgrade-v4.md | new MMKV() → createMMKV(), .delete() → .remove() |
| Storage growing too large | limits-and-gotchas.md | Trim or move to SQLite |
| Multi-process data sharing | limits-and-gotchas.md | Set mode: 'multi-process' |