Key-Value Storage: AsyncStorage, MMKV & SecureStore

Choose between AsyncStorage, MMKV and SecureStore and use them safely for settings and tokens.

Key-value storage is for small pieces of data. The three common options differ in speed and in safety.

Core concepts

  1. AsyncStorage: A simple asynchronous key-value store that works in Expo Go. Good for non-sensitive preferences and cached JSON. — AsyncStorage docs
  2. MMKV: A very fast synchronous store (via JSI) suited to frequently read values. It requires a development build rather than Expo Go. — react-native-mmkv
  3. SecureStore: Stores small secrets in the keychain/keystore. Values have size limits, so store tokens, not large blobs. — Expo SecureStore
  4. Wrap storage behind an interface: Create lib/storage.ts so screens never import a storage library directly; swapping AsyncStorage for MMKV later is then one file. — Expo docs

Concept videos

YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.

Explanation

JSON in, JSON out

Storage holds strings. Serialise with JSON and validate on read, because old app versions may have saved a different shape.

Do not store everything

Large lists belong in SQLite. Key-value stores are for small, simple data.

What Is It?

Key-value storage maps a string key to a small saved value.

Why Should I Care?

It is the simplest way to persist settings, flags and tokens.

Real World Analogy

It is a row of labelled lockers: you can open one by its label, but you would not store a whole library in lockers.

Visual Mental Model

text
key -> value (string)
secret key -> SecureStore
fast key -> MMKV
simple key -> AsyncStorage

Smallest Possible Example

ts
import AsyncStorage from '@react-native-async-storage/async-storage';

export async function getJson<T>(key: string, fallback: T): Promise<T> {
  const raw = await AsyncStorage.getItem(key);
  return raw ? (JSON.parse(raw) as T) : fallback;
}

Common Mistakes

❌ Reading storage on every render.

Read once at startup into state or a store.

❌ No fallback when parsing fails.

Corrupt or old data would crash the app; validate and fall back.

Build This Mini Project

Create lib/storage.ts with typed get/set helpers and a SecureStore-backed token helper.

Prompts for Cursor, Claude Code & Codex

Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.

Storage wrapper

text
Create lib/storage.ts that exposes getJson/setJson (AsyncStorage) and getSecret/setSecret (SecureStore) with typed helpers and safe JSON parsing. Replace direct storage imports across the app.

Rules, databases & blogs to use

Resources

Threads in the same domain as this chapter — go deeper on iHateReading without leaving the roadmap.

Vector search using vector embeddings cover

Vector search using vector embeddings

Embeddings, similarity search, and RAG-shaped memory for apps.

Agent harnessing: the part of building AI agents nobody talks about cover

Agent harnessing: the part of building AI agents nobody talks about

Loop, tools, memory, sandbox, and tracing live in your code — not the model weights.

Firebase, Supabase and Clerk authentication cover

Firebase, Supabase and Clerk authentication

Auth options for apps compared.