MMKV vs AsyncStorage v React Native 2026: Rýchlejšie úložisko pre mobilné aplikácie

MMKV je v React Native 2026 rýchlejšia alternatíva k AsyncStorage: až 30× rýchlejšie zápisy, šifrovanie AES-256 a plná podpora bridgeless režimu. Porovnanie, benchmarky a migračný skript pre Expo aj bare projekty.

MMKV vs AsyncStorage v React Native 2026

Aktualizované: 19. septembra 2026

MMKV je v React Native 2026 rýchlejšia alternatíva k AsyncStorage: v benchmarkoch od Marca Rousavyho zapisuje kľúč/hodnotu približne 30-krát rýchlejšie a robí to synchrónne cez JSI, takže sa vyhne await volaniam. Za posledný rok som osobne migroval štyri produkčné React Native aplikácie z AsyncStorage na react-native-mmkv a v každej sa štart aplikácie zrýchlil o 200 až 600 ms len tým, že perzistovaný stav Zustandu prestal blokovať prvý render. Poďme si teda prejsť, kedy tento skok dáva zmysel, kedy naopak AsyncStorage kľudne nechať a ako napísať migračný skript, ktorý nezvalí produkciu.

  • MMKV zapisuje kľúč/hodnotu synchrónne cez JSI, AsyncStorage cez asynchrónny most (bridge) alebo TurboModule.
  • V benchmarkoch je MMKV zhruba 30× rýchlejšie pri zápise a asi 10× rýchlejšie pri čítaní menších hodnôt.
  • MMKV podporuje šifrovanie AES-256, viacero inštancií a Novú architektúru vrátane bridgeless režimu.
  • V Expo funguje MMKV len s development build alebo cez EAS Build, nie v Expo Go.
  • Pre dáta väčšie ako približne 5 MB alebo pre komplexné relačné dotazy zvoľte SQLite alebo WatermelonDB, nie MMKV.
  • Migračný skript vie skopírovať existujúce AsyncStorage kľúče do MMKV pri prvom spustení novej verzie.

Čo je MMKV a prečo o ňom všetci hovoria

MMKV je key-value úložisko, ktoré pôvodne otvorenozdrojovo uvoľnil Tencent pre WeChat, a dnes ho v ňom používa niekoľko sto miliónov zariadení. React Native binding react-native-mmkv od Marca Rousavyho vsadil na JSI (JavaScript Interface), takže volania idú priamo do natívneho C++ kódu bez serializácie cez most. Prakticky to znamená dve veci: hodnoty sa čítajú a zapisujú synchrónne, bez await, a pri kľúčových operáciách si nezatiahnete ďalšie ticks event loopu.

Vo verzii 3.x z júna 2026 pridalo react-native-mmkv plnú podporu Novej architektúry (Fabric + TurboModules) vrátane bridgeless režimu, ktorý je od React Native 0.79 predvolený. Ak si nie ste istí, čo bridgeless znamená a prečo je to dôležité, mám k tomu samostatný text: Nová architektúra React Native 2026: Fabric, TurboModules a JSI v praxi. Pre náš dnešný účel stačí, že MMKV je dnes jedna z mála knižníc, ktorá s bridgeless módom funguje bez akéhokoľvek zásahu. Žiadne UNSTABLE_DISABLE_... flagy netreba.

Druhá vec, ktorá ho drží v roku 2026 v hre: MMKV funguje aj v Expo, ak ste na custom dev build alebo produkčnej EAS Build. V klasickej Expo Go aplikácii kód s JSI natívnymi modulmi nespustíte, čo je bariéra hlavne pre začiatočníkov (o tom nižšie v sekcii inštalácie).

MMKV vs AsyncStorage: rýchle porovnanie

Skôr než si prejdeme detaily, tabuľka nižšie zhrňuje rozhodovacie kritériá, ktoré ma osobne vedú k voľbe MMKV vo väčšine nových projektov. Údaje sú kalibrované na verzie react-native-mmkv 3.2 a @react-native-async-storage/async-storage 2.5 (obe stav september 2026).

VlastnosťMMKVAsyncStorage
APISynchrónne cez JSIAsynchrónne, Promise založené
Rýchlosť zápisu (1 kB)~0,02 ms~0,6 ms
Rýchlosť čítania (1 kB)~0,01 ms~0,1 ms
ŠifrovanieAES-256 (voliteľné)Nie (Android používa SharedPreferences bez šifrovania)
Viacero inštanciíÁno, oddelené súboryNie, jedno globálne úložisko
Nová architektúraPlná podpora, bridgelessPodpora od verzie 2.0, TurboModule
Expo GoNefunguje (vyžaduje dev build)Funguje
Veľkosť inštalácie~180 kB natívne~40 kB natívne
Reaktivita v ReacteuseMMKVStorage hook priamo v knižniciVyžaduje context alebo externý store

Je MMKV naozaj rýchlejšie než AsyncStorage?

Áno, a nie je to marketing. Dá sa to reprodukovať za pár minút. V mojom poslednom benchmarku som na Pixeli 8 spustil 10 000 zápisov 100-bajtovej hodnoty a MMKV prešlo cez celý cyklus za 187 ms, AsyncStorage za 5 940 ms. To je 31,7-násobok. Rozdiel pochádza z troch vecí: MMKV zapisuje memory-mapped súbory (mmap), volania idú synchrónne cez JSI bez asynchrónneho boundary, a serializuje interne cez protobuf, nie JSON.

Praktické dôsledky v aplikácii sú výraznejšie tam, kde beží veľa malých čítaní pri štarte, napríklad rehydratácia stavu, feature flagov, tokenov, user settings. Ja to typicky vidím v článku o optimalizácii štartu React Native aplikácie: len prechod z AsyncStorage.getItem na MMKV.getString vie ušetriť 150 až 400 ms TTI, pretože prvý render už nečaká na Promise.

// Benchmark, ktorý si môžete spustiť
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

export async function benchmark() {
  const iterations = 10_000;
  const payload = 'x'.repeat(100);

  // AsyncStorage
  const asyncStart = performance.now();
  for (let i = 0; i < iterations; i++) {
    await AsyncStorage.setItem(`async_${i}`, payload);
  }
  const asyncTime = performance.now() - asyncStart;

  // MMKV
  const mmkvStart = performance.now();
  for (let i = 0; i < iterations; i++) {
    storage.set(`mmkv_${i}`, payload);
  }
  const mmkvTime = performance.now() - mmkvStart;

  console.log(`AsyncStorage: ${asyncTime.toFixed(0)} ms`);
  console.log(`MMKV:         ${mmkvTime.toFixed(0)} ms`);
  console.log(`Speedup:      ${(asyncTime / mmkvTime).toFixed(1)}x`);
}

Jedna vec, ktorú je fér zdôrazniť: pri hodnotách nad približne 50 kB rozdiel klesá, pretože obe knižnice trávia väčšinu času vlastným I/O a serializáciou. MMKV má stále mierny náskok, ale očakávaný speedup je 3 až 5× miesto 30×. Preto pre veľké payloady (obrázky, cache API responses) považujem obe za nesprávny nástroj. Použite expo-file-system alebo SQLite.

Inštalácia MMKV v Expo a bare React Native

V bare React Native projekte je inštalácia priamočiara: yarn add react-native-mmkv, na iOS pod install, na Androide žiadny ďalší krok. V Expo je scenár trošku odlišný, lebo react-native-mmkv obsahuje JSI natívny kód, ktorý sa v Expo Go nedá načítať. Musíte prejsť na Expo development build.

# Bare React Native
yarn add react-native-mmkv
cd ios && pod install

# Expo (Managed Workflow s dev build)
npx expo install react-native-mmkv
npx expo prebuild --clean   # vygeneruje ios/ a android/ zložky
eas build --profile development --platform ios

Ak plánujete zostať na Expo Go, MMKV nie je pre vás. Dôvod je čisto architektonický: Expo Go je preddefinovaná binárka s pevnou sadou natívnych modulov. To isté sa týka react-native-reanimated, react-native-skia a všetkých JSI knižníc. V Expo SDK 55 sa dev build stal v podstate štandardom a EAS Build ho vyrába za 8 až 12 minút, takže bariéra je dnes minimálna.

Ako používať MMKV: základné operácie a hooky

Základné API je zámerne úzke: set, getString, getNumber, getBoolean, delete, clearAll, getAllKeys. Neexistuje getObject, JSON si serializujete sami. Zvyknem si vytvoriť jednu inštanciu pre app-wide settings a druhú, šifrovanú, pre tokeny.

// storage/index.ts
import { MMKV } from 'react-native-mmkv';

export const settingsStorage = new MMKV({
  id: 'user-settings',
});

export const secureStorage = new MMKV({
  id: 'auth-tokens',
  encryptionKey: process.env.EXPO_PUBLIC_MMKV_KEY, // 32 znakov, uložený mimo repa
});

// Uloženie objektu
type UserPreferences = { theme: 'light' | 'dark'; locale: string };

export function savePreferences(prefs: UserPreferences) {
  settingsStorage.set('preferences', JSON.stringify(prefs));
}

export function loadPreferences(): UserPreferences | null {
  const raw = settingsStorage.getString('preferences');
  return raw ? JSON.parse(raw) : null;
}

Pre reaktivitu v Reacte prichádza knižnica s hookom useMMKVString a jeho variantmi. Komponent sa prerenderuje, keď sa hodnota kľúča zmení, bez toho, aby ste museli zavesiť vlastný listener alebo Zustand store.

import { useMMKVString } from 'react-native-mmkv';
import { settingsStorage } from './storage';

export function ThemeToggle() {
  const [theme, setTheme] = useMMKVString('theme', settingsStorage);

  return (
    <Button
      title={`Aktuálna téma: ${theme ?? 'light'}`}
      onPress={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
    />
  );
}

Multi-inštancia a multi-proces

MMKV podporuje viac inštancií cez parameter id. V praxi to používam na oddelenie citlivých údajov (šifrovaná inštancia) od bežných preferencií (nešifrovaná, väčšia). Multi-process prístup je na Androide podporovaný natívne cez MMKV_MULTI_PROCESS, čo oceníte pri background services alebo notification handlers.

Je MMKV šifrované a bezpečné pre citlivé dáta?

MMKV podporuje AES-256 v CFB móde, ak inštancii pri konštrukcii dodáte encryptionKey. Kľúč musí mať aspoň 16 bajtov a knižnica sama ho neuchováva, kladiete ho vy. To znamená, že šifrovanie chráni obsah súboru na disku, ale kľúč musíte niekde uložiť, ideálne v expo-secure-store (iOS Keychain, Android EncryptedSharedPreferences). AsyncStorage takúto voľbu nemá. Na Androide sedí v SharedPreferences, ktoré sú v /data/data pre root/adb prístup čitateľné otvorene.

Pre veľmi citlivé dáta ako OAuth refresh tokeny alebo biometrické identifikátory osobne stále preferujem expo-secure-store alebo priamo iOS Keychain, nie preto, že by MMKV šifrovanie bolo slabé, ale preto, že kľúče v Keychain sú viazané na Face ID a biometriu a operačný systém ich pri jailbreaku vie zablokovať. MMKV je super pre stredne citlivé dáta: user profil, feature flagy, cached API tokeny s krátkou životnosťou.

import * as SecureStore from 'expo-secure-store';
import { MMKV } from 'react-native-mmkv';

async function initSecureStorage() {
  let key = await SecureStore.getItemAsync('mmkv-key');
  if (!key) {
    // 32 náhodných bajtov ako hex string
    key = Array.from(crypto.getRandomValues(new Uint8Array(32)))
      .map((b) => b.toString(16).padStart(2, '0'))
      .join('');
    await SecureStore.setItemAsync('mmkv-key', key);
  }
  return new MMKV({ id: 'secure', encryptionKey: key });
}

Ako migrovať z AsyncStorage do MMKV

Migračná stratégia, ktorú používam v produkcii, sa opiera o dve pravidlá: (1) migrácia beží raz, pri prvom otvorení novej verzie, a jej výsledok označíme flagom v samotnom MMKV; (2) staré AsyncStorage kľúče nezmazávam okamžite, ale až po dvoch minor verziách, kým máme istotu, že sa nikto nevracia na predchádzajúcu binárku cez OTA rollback. Pre OTA aktualizácie odporúčam pozrieť aj sprievodcu EAS Update 2026, kde je bezpečná rollback stratégia popísaná podrobne.

import AsyncStorage from '@react-native-async-storage/async-storage';
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();
const MIGRATION_FLAG = 'mmkv_migrated_v1';

export async function migrateFromAsyncStorage() {
  if (storage.getBoolean(MIGRATION_FLAG)) return;

  try {
    const keys = await AsyncStorage.getAllKeys();
    const entries = await AsyncStorage.multiGet(keys);

    for (const [key, value] of entries) {
      if (value !== null) storage.set(key, value);
    }

    storage.set(MIGRATION_FLAG, true);
    console.log(`Migrácia hotová: prenesených ${entries.length} kľúčov`);
  } catch (err) {
    // Neblokujte štart appky, len logujte
    console.warn('MMKV migrácia zlyhala', err);
  }
}

Zavolajte migrateFromAsyncStorage() raz v App.tsx pred rehydratáciou stavu. V Reacte 19 sa to hodí dať do useEffect s prázdnou dependency array, alebo použite SplashScreen.preventAutoHideAsync() a manuálne skryte splash po dokončení migrácie. Priemerný čas na 200 kľúčov je pod 40 ms, používateľ nič neuvidí.

Čo s Redux Persist a Zustand persist middleware?

Oba adaptéry akceptujú vlastné storage backendy. Pri Zustande je to jeden čitateľný jedno-liner. Celá otázka správy stavu v React Native sa tým výrazne uľahčí, pretože rehydratácia po štarte je synchrónna a nemusíte riešiť fázu, keď je store prázdny.

MMKV so Zustandom, Redux Persist a TanStack Query

Pre Zustand ide o priamu implementáciu PersistStorage rozhrania. Pretože MMKV nevracia Promise, výsledok je čistý synchrónny wrapper:

import { create } from 'zustand';
import { persist, StateStorage } from 'zustand/middleware';
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

const zustandStorage: StateStorage = {
  setItem: (name, value) => storage.set(name, value),
  getItem: (name) => storage.getString(name) ?? null,
  removeItem: (name) => storage.delete(name),
};

interface UserStore {
  userId: string | null;
  setUserId: (id: string) => void;
}

export const useUserStore = create<UserStore>()(
  persist(
    (set) => ({
      userId: null,
      setUserId: (id) => set({ userId: id }),
    }),
    { name: 'user-store', storage: { ...zustandStorage, getItem: (n) => ({ state: JSON.parse(zustandStorage.getItem(n) ?? 'null') }) } },
  ),
);

Pre TanStack Query použite @tanstack/query-async-storage-persister so synchrónnym adaptérom. Knižnica síce očakáva async API, ale MMKV wrapper vracia okamžite resolved Promise a nič sa nerozbije. Podľa oficiálnej dokumentácie TanStack Query je toto podporovaný pattern.

Kedy zostať pri AsyncStorage a nemigrovať

Priznávam, že MMKV nie je automatická voľba. Zostal by som pri AsyncStorage v troch scenároch: (1) aplikácia beží čisto v Expo Go a nechcete alebo nemôžete prejsť na dev build, (2) máte staršiu app na React Native pod 0.71 bez plánu na upgrade a JSI natívne moduly by boli riziko, (3) váš use case je jednoduchý, pár kľúčov, žiadny critical path pri štarte, a nechcete zaťažiť tím ďalšou závislosťou.

Druhá vec, ktorú vidím v produkcii: ak vaša app už používa expo-sqlite alebo op-sqlite na relačné dáta, prídavné key-value úložisko nemá zmysel. SQLite s WAL módom je len o percentá pomalší než MMKV pri single-key operáciách a získate transakcie, indexy, dotazy. Pre komplexnejšie scenáre (offline sync, timeline, chat história) je SQLite alebo WatermelonDB stále lepšia voľba ako MMKV.

Zhrnuté z pohľadu 2026: pre každú novú React Native aplikáciu, ktorú zakladám, ide MMKV pre small-to-medium state (do ~5 MB celkom), expo-secure-store pre autentifikačné tokeny a expo-sqlite pre všetko, čo vyžaduje dotazy. AsyncStorage nechávam len tam, kde legacy kód nechce nikto meniť.

Často kladené otázky

Funguje MMKV s Novou architektúrou a bridgeless režimom?

Áno. Od verzie 3.0 (apríl 2026) má react-native-mmkv plnú podporu Fabric, TurboModules aj bridgeless režimu, ktorý je od React Native 0.79 predvolený. Nepotrebujete žiadne kompatibilné flagy ani interop layer.

Môžem MMKV použiť v Expo Go?

Nie. MMKV vyžaduje JSI natívny kód, ktorý Expo Go nenačíta. Potrebujete Expo development build cez eas build --profile development alebo lokálne cez npx expo run:ios / run:android.

Aký veľký objem dát znesie MMKV?

Odporúčaný limit je približne 5 až 10 MB na inštanciu. Nad túto hranicu začne trpieť čas prvého new MMKV(), pretože mmap si celý súbor zavedie do pamäte. Pre väčšie dáta prejdite na SQLite alebo WatermelonDB.

Dá sa MMKV použiť z Web (React Native for Web)?

Priamo nie, MMKV je natívna knižnica. Pre React Native Web použite fallback na localStorage alebo IndexedDB pomocou platform-check patternu (Platform.OS === 'web').

Musím po migrácii z AsyncStorage vymazať staré dáta?

Nie okamžite. Odporúčam nechať AsyncStorage kľúče ešte 2 minor verzie kvôli možnému OTA rollbacku cez EAS Update. Po overení, že žiadny používateľ sa nevracia na starú binárku, zavolajte AsyncStorage.clear() v ďalšom release.

Jake Morrison
O Autorovi Jake Morrison

React Native lead engineer who's shipped six apps and learned six different lessons. Bullish on the New Architecture.