Sitemap

🚀 Optimizing React Native Performance with MMKV

4 min readMay 10, 2025

--

Press enter or click to view image in full size

How to supercharge your app’s storage with native speed

In mobile development, performance isn’t just a nice-to-have — it’s a dealbreaker. Users expect apps to load instantly, feel buttery smooth, and never lag. A surprisingly common source of bottlenecks in React Native apps? Storage.

Whether it’s caching authentication tokens, storing user preferences, or managing flags and settings, the default AsyncStorage can become a performance hurdle. That’s where MMKV comes in.

Get adarshpy’s stories in your inbox

Join Medium for free to get updates from this writer.

In this post, we’ll explore how to integrate MMKV into a React Native app, along with Zustand and Redux, and the real-world performance gains it can unlock.

🧱 The Problem with AsyncStorage

AsyncStorage is simple and works out of the box, but it comes with trade-offs:

  • ❌ Slower read/write speeds
  • ❌ JS thread involvement leads to frame drops
  • ❌ Noticeable delays in app startup
  • ❌ Lack of built-in encryption

These issues become more apparent as your app scales or targets lower-end devices. If storage is accessed frequently — say, for feature flags, auth state, or UI preferences — AsyncStorage can quickly become the silent killer of performance.

⚡ Meet MMKV

MMKV is a high-performance key-value storage library developed by WeChat, written in C++ and optimized for mobile. It offers fast, synchronous access to data directly from the native layer — meaning the JS thread isn’t blocked.

Why MMKV is better:

Feature AsyncStorage MMKV Speed ❌ Slow ✅ 30x faster JS Thread Usage ❌ Blocks thread ✅ Runs on native layer Encryption ❌ Manual required ✅ Built-in Synchronous Access ❌ No ✅ Yes App Startup Performance ❌ Laggy ✅ Near-instant

🛠️ Installation

Getting started is simple:

yarn add react-native-mmkv
# or
npm install react-native-mmkv

🧪 Setting Up MMKV

Create a simple storage.ts file:

import { MMKV } from 'react-native-mmkv';
export const storage = new MMKV();

Now wrap this in a clean service layer:

// storageService.ts
import { storage } from './storage';
export const StorageService = {
set: (key: string, value: string) => storage.set(key, value),
get: (key: string): string | undefined => storage.getString(key),
delete: (key: string) => storage.delete(key),
clear: () => storage.clearAll(),
};

Usage:

StorageService.set('theme', 'dark');
const theme = StorageService.get('theme');

🔒 Optional: Add Encryption

For sensitive data, MMKV supports encryption out of the box:

const secureStorage = new MMKV({ encryptionKey: 'your-encryption-key' });

💡 Pro Tip: Use native keychain libraries like react-native-keychain to securely generate and manage encryption keys instead of hardcoding them.

🌿 Use with Zustand (Example)

MMKV shines when integrated with persistent state libraries like Zustand:

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { storage } from './storage';
const useUserStore = create(
persist(
(set) => ({
token: '',
setToken: (value: string) => set({ token: value }),
}),
{
name: 'user-store',
getStorage: () => ({
getItem: (key) => storage.getString(key) ?? null,
setItem: (key, value) => storage.set(key, value),
removeItem: (key) => storage.delete(key),
}),
}
)
);

This results in instant state hydration and zero performance hit on startup.

🧩 Use with Redux + redux-persist

Here’s how to use MMKV with Redux by creating a custom storage adapter for redux-persist.

Create the MMKV Storage Adapter

// mmkvStorage.ts
import { storage } from './storage';
import type { Storage } from 'redux-persist';
export const mmkvStorage: Storage = {
setItem: (key, value) => {
storage.set(key, value);
return Promise.resolve(true);
},
getItem: (key) => {
const value = storage.getString(key);
return Promise.resolve(value ?? null);
},
removeItem: (key) => {
storage.delete(key);
return Promise.resolve();
},
};

Configure Redux Persist

import { persistStore, persistReducer } from 'redux-persist';
import { mmkvStorage } from './mmkvStorage';
import { rootReducer } from './reducers';
const persistConfig = {
key: 'root',
storage: mmkvStorage,
whitelist: ['auth', 'settings'], // persist only desired reducers
};
const persistedReducer = persistReducer(persistConfig, rootReducer);export const store = createStore(persistedReducer);
export const persistor = persistStore(store);

This gives you native-speed Redux persistence without sacrificing encryption or performance.

📈 Real-World Benefits

In real production apps, switching from AsyncStorage to MMKV resulted in:

  • 🚀 App startup time reduced by up to 0.5 seconds
  • 🧠 JS thread no longer blocked by storage reads
  • 🔐 Secure storage for tokens and flags with minimal overhead
  • 💨 Lightning-fast config loads and preference access

✅ Best Practices

To get the most out of MMKV:

  • Keep all storage logic encapsulated in service layers
  • Avoid storing large or deeply nested JSON blobs — flatten where possible
  • Use MMKV for small/medium-size items (tokens, booleans, strings, flags)
  • For large structured data, consider SQLite or WatermelonDB

🔚 Final Thoughts

React Native apps are only as fast as their weakest link. Storage might seem trivial, but it plays a huge role in app performance and smooth UX.

MMKV is a powerful drop-in replacement for AsyncStorage that brings native-speed persistence, encryption, and reliability with minimal effort. Whether you’re building a lightweight utility or scaling a complex production app, this small change can make a massive impact.

If you found this helpful, feel free to share it with others building high-performance React Native apps.
Follow me on Medium for more mobile dev tips, performance tricks, and architecture guides.

--

--