/mobile-storage-mmkv
MMKV high-performance key-value storage for React Native - synchronous JSI-based reads/writes, encryption, typed hooks, multiple instances, listeners, persistence middleware adapters
$ npx -y skills add agents-inc/skills --skill mobile-storage-mmkv --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/mobile-storage-mmkv
Context preview
The summary Claude sees to decide when to auto-load this skill.
MMKV high-performance key-value storage for React Native - synchronous JSI-based reads/writes, encryption, typed hooks, multiple instances, listeners, persistence middleware adapters
SKILL.md
mobile-storage-mmkv.SKILL.mdname: mobile-storage-mmkv
description: MMKV high-performance key-value storage for React Native - synchronous JSI-based reads/writes, encryption, typed hooks, multiple instances, listeners, persistence middleware adapters
MMKV Storage Patterns
> **Quick Guide:** Use `createMMKV()` for synchronous key-value storage (~30x faster than AsyncStorage). One singleton instance per concern (global app, per-user). Use typed hooks (`useMMKVString`, `useMMKVObject`) for reactive components. Enable encryption with `encryptionKey` for sensitive data. V4 is a Nitro Module requiring `react-native-nitro-modules` and React Native 0.75+.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST reuse a single MMKV instance per concern -- NEVER call `createMMKV()` on every render or in component bodies)**
**(You MUST use typed getters (`getString`, `getNumber`, `getBoolean`) -- NEVER parse the return value of the wrong getter)**
**(You MUST use `remove()` to delete keys -- `delete()` was renamed in v4 due to C++ keyword conflict)**
**(You MUST install `react-native-nitro-modules` alongside `react-native-mmkv` -- v4 is a Nitro Module)**
</critical_requirements>
---
**Auto-detection:** MMKV, react-native-mmkv, createMMKV, useMMKVString, useMMKVNumber, useMMKVBoolean, useMMKVObject, useMMKVBuffer, useMMKVListener, useMMKVKeys, addOnValueChangedListener, encryptionKey, mmkv storage, key-value storage React Native
**When to use:**
- Persisting user preferences, auth tokens, or cached data synchronously
- Replacing AsyncStorage for faster reads/writes (~30x improvement)
- Encrypting sensitive data at rest with AES-128 or AES-256
- Sharing storage between iOS app and extensions via App Groups
- Building reactive UIs that re-render on storage changes (hooks)
- Isolating data per user or feature with multiple named instances
**Key patterns covered:**
- Instance creation with `createMMKV()` and configuration options
- Typed getters/setters and object serialization
- React hooks for reactive storage (`useMMKVString`, `useMMKVObject`, etc.)
- Value change listeners (`addOnValueChangedListener`, `useMMKVListener`)
- Multiple instances for data isolation (global vs per-user)
- Encryption at rest (AES-128/AES-256)
- Persistence middleware adapter (generic `StateStorage` interface)
- Migration from AsyncStorage
**When NOT to use:**
- Large binary files or media (use the filesystem)
- Relational or queryable data (use a local database)
- Data that must sync across devices (use a cloud-synced solution)
- Server state caching with invalidation (use your data fetching layer)
**Detailed Resources:**
- [examples/core.md](examples/core.md) - Instance setup, typed access, hooks, listeners
- [examples/advanced.md](examples/advanced.md) - Encryption, multiple instances, App Groups, multi-process, migration
- [examples/persistence.md](examples/persistence.md) - State management persistence adapter, hydration handling
- [reference.md](reference.md) - API reference, V3-to-V4 migration table, migration checklist
---
<philosophy>
Philosophy
MMKV is a **synchronous**, JSI-based key-value store built on top of Tencent's battle-tested C++ library. The key advantage over AsyncStorage is that reads and writes are synchronous -- no `await`, no Promises, no bridge serialization. This eliminates an entire class of race conditions and simplifies code.
**Core principles:**
1. **Synchronous by design** -- `getString()` returns immediately, no async wrappers needed 2. **One instance per concern** -- export a singleton; never create instances inside components 3. **Typed access** -- use the correct getter for the stored type; MMKV does not auto-convert 4. **Encrypt sensitive data** -- tokens, keys, PII should use `encryptionKey` option 5. **Hooks for reactivity** -- `useMMKVString` etc. trigger re-renders on changes, replacing manual subscriptions
**Performance comparison with AsyncStorage:**
| Operation | AsyncStorage | MMKV | Speedup | |----------------|-------------|--------|---------| | Read 1 key | ~5ms | ~0.015ms | ~300x | | Write 1 key | ~8ms | ~0.018ms | ~440x | | Read 1000 keys | ~200ms | ~3ms | ~65x |
Benchmarks vary by device, but MMKV is consistently 30-100x faster for typical operations.
**V4 architecture:** MMKV v4 is a Nitro Module (not a TurboModule). This means it uses `react-native-nitro-modules` for the native bridge, requires React Native 0.75+, and the JS API uses `createMMKV()` instead of `new MMKV()`.
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Instance Creation and Singleton Export
Create one instance per storage concern at module scope. Never inside a component or hook body.
import { createMMKV } from "react-native-mmkv";
// Global app storage -- reuse this everywhere
export const storage = createMMKV();
// Named instance for user-specific data
export const createUserStorage = (userId: string) =>
createMMKV({ id: `user-${userId}` });**Why good:** Module-level creation runs once, all consumers share the same native instance, no wasted allocations
// BAD: Creating instance inside component
function Settings() {
const storage = createMMKV(); // New native instance every render
// ...
}**Why bad:** Creates a new native MMKV instance on every render, wastes memory, defeats instance caching
See [examples/core.md](examples/core.md) for full configuration options (path, encryption, readOnly, compareBeforeSet).
---
Pattern 2: Typed Getters and Setters
MMKV stores values by type. Always use the matching getter for what was stored.
// Set typed values
storage.set("user.name", "Alice");
storage.set("user.age", 28);
storage.set("onboarded", true);
// Get with correct typed getter
const name = storage.getStrRead more
name: mobile-storage-mmkv description: MMKV high-performance key-value storage for React Native - synchronous JSI-based reads/writes, encryption, typed hooks, multiple instances, listeners, persistence middleware adapters
MMKV Storage Patterns
> **Quick Guide:** Use `createMMKV()` for synchronous key-value storage (~30x faster than AsyncStorage). One singleton instance per concern (global app, per-user). Use typed hooks (`useMMKVString`, `useMMKVObject`) for reactive components. Enable encryption with `encryptionKey` for sensitive data. V4 is a Nitro Module requiring `react-native-nitro-modules` and React Native 0.75+.
---
<critical_requirements>
CRITICAL: Before Using This Skill
> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)
**(You MUST reuse a single MMKV instance per concern -- NEVER call `createMMKV()` on every render or in component bodies)**
**(You MUST use typed getters (`getString`, `getNumber`, `getBoolean`) -- NEVER parse the return value of the wrong getter)**
**(You MUST use `remove()` to delete keys -- `delete()` was renamed in v4 due to C++ keyword conflict)**
**(You MUST install `react-native-nitro-modules` alongside `react-native-mmkv` -- v4 is a Nitro Module)**
</critical_requirements>
---
**Auto-detection:** MMKV, react-native-mmkv, createMMKV, useMMKVString, useMMKVNumber, useMMKVBoolean, useMMKVObject, useMMKVBuffer, useMMKVListener, useMMKVKeys, addOnValueChangedListener, encryptionKey, mmkv storage, key-value storage React Native
**When to use:**
- Persisting user preferences, auth tokens, or cached data synchronously
- Replacing AsyncStorage for faster reads/writes (~30x improvement)
- Encrypting sensitive data at rest with AES-128 or AES-256
- Sharing storage between iOS app and extensions via App Groups
- Building reactive UIs that re-render on storage changes (hooks)
- Isolating data per user or feature with multiple named instances
**Key patterns covered:**
- Instance creation with `createMMKV()` and configuration options
- Typed getters/setters and object serialization
- React hooks for reactive storage (`useMMKVString`, `useMMKVObject`, etc.)
- Value change listeners (`addOnValueChangedListener`, `useMMKVListener`)
- Multiple instances for data isolation (global vs per-user)
- Encryption at rest (AES-128/AES-256)
- Persistence middleware adapter (generic `StateStorage` interface)
- Migration from AsyncStorage
**When NOT to use:**
- Large binary files or media (use the filesystem)
- Relational or queryable data (use a local database)
- Data that must sync across devices (use a cloud-synced solution)
- Server state caching with invalidation (use your data fetching layer)
**Detailed Resources:**
- [examples/core.md](examples/core.md) - Instance setup, typed access, hooks, listeners
- [examples/advanced.md](examples/advanced.md) - Encryption, multiple instances, App Groups, multi-process, migration
- [examples/persistence.md](examples/persistence.md) - State management persistence adapter, hydration handling
- [reference.md](reference.md) - API reference, V3-to-V4 migration table, migration checklist
---
<philosophy>
Philosophy
MMKV is a **synchronous**, JSI-based key-value store built on top of Tencent's battle-tested C++ library. The key advantage over AsyncStorage is that reads and writes are synchronous -- no `await`, no Promises, no bridge serialization. This eliminates an entire class of race conditions and simplifies code.
**Core principles:**
1. **Synchronous by design** -- `getString()` returns immediately, no async wrappers needed 2. **One instance per concern** -- export a singleton; never create instances inside components 3. **Typed access** -- use the correct getter for the stored type; MMKV does not auto-convert 4. **Encrypt sensitive data** -- tokens, keys, PII should use `encryptionKey` option 5. **Hooks for reactivity** -- `useMMKVString` etc. trigger re-renders on changes, replacing manual subscriptions
**Performance comparison with AsyncStorage:**
| Operation | AsyncStorage | MMKV | Speedup | |----------------|-------------|--------|---------| | Read 1 key | ~5ms | ~0.015ms | ~300x | | Write 1 key | ~8ms | ~0.018ms | ~440x | | Read 1000 keys | ~200ms | ~3ms | ~65x |
Benchmarks vary by device, but MMKV is consistently 30-100x faster for typical operations.
**V4 architecture:** MMKV v4 is a Nitro Module (not a TurboModule). This means it uses `react-native-nitro-modules` for the native bridge, requires React Native 0.75+, and the JS API uses `createMMKV()` instead of `new MMKV()`.
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Instance Creation and Singleton Export
Create one instance per storage concern at module scope. Never inside a component or hook body.
import { createMMKV } from "react-native-mmkv";
// Global app storage -- reuse this everywhere
export const storage = createMMKV();
// Named instance for user-specific data
export const createUserStorage = (userId: string) =>
createMMKV({ id: `user-${userId}` });**Why good:** Module-level creation runs once, all consumers share the same native instance, no wasted allocations
// BAD: Creating instance inside component
function Settings() {
const storage = createMMKV(); // New native instance every render
// ...
}**Why bad:** Creates a new native MMKV instance on every render, wastes memory, defeats instance caching
See [examples/core.md](examples/core.md) for full configuration options (path, encryption, readOnly, compareBeforeSet).
---
Pattern 2: Typed Getters and Setters
MMKV stores values by type. Always use the matching getter for what was stored.
// Set typed values
storage.set("user.name", "Alice");
storage.set("user.age", 28);
storage.set("onboarded", true);
// Get with correct typed getter
const name = storage.getStrShowing the first part of this file.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

