DEV Community

Cover image for The Complete Guide to Offline Storage in React Native (2026)
Jules Sarah
Jules Sarah

Posted on

The Complete Guide to Offline Storage in React Native (2026)

  • Offline storage is five categories, not one library: key-value, secure, structured, file system, and server-state cache.
  • MMKV is the new default over AsyncStorage — roughly 30× faster with synchronous reads.
  • The offline-first pattern has four parts: local-first reads, optimistic writes, a durable mutation queue, and a sync engine.
  • Conflict resolution: last-write-wins is fine for most consumer apps. CRDTs are overkill unless you're building a collaborative editor.

Most React Native apps treat the network as an always-on dependency, and it shows the moment a request stalls.

Offline storage isn't one library — it's a stack: key-value stores for preferences, secure enclaves for tokens, structured DBs for domain data, and query caches for server state.

This post walks through the whole stack and the offline-first pattern that ties it together.

The five categories of RN offline storage

  1. Key-valueAsyncStorage (compat) or MMKV (default). MMKV is ~30× faster and supports synchronous reads.
  2. Secureexpo-secure-store or react-native-keychain. Backed by iOS Keychain / Android Keystore.
  3. Structuredexpo-sqlite, op-sqlite (JSI, synchronous), WatermelonDB (reactive + sync), Realm (Atlas Device Sync).
  4. File systemexpo-file-system for media. Never base64 blobs into KV storage.
  5. Server-state cache — TanStack Query with persistQueryClient, backed by MMKV.

Comparison table

Library Type Perf Encryption Best for
AsyncStorage KV Community fork Legacy / compat
MMKV KV ~30× Built-in New default
expo-secure-store Secure KV OS keychain Tokens
op-sqlite SQL JSI SQLCipher Structured data
WatermelonDB Reactive DB Lazy SQLCipher Large offline lists + sync
Realm Object DB Fast Yes Atlas Device Sync

The offline-first pattern

Four moving parts:

  1. Local-first reads. The UI always reads from the local store. The network populates the store; the store renders the UI.
  2. Optimistic writes. The UI updates immediately, before the server acknowledges.
  3. Mutation queue. A durable list (SQLite or MMKV) of pending server-side changes, each with a client ID.
  4. Sync engine. A background worker drains the queue with exponential backoff and reconciles conflicts.
async function markMessageAsRead(id: string) {
  db.write(() => {
    db.messages.update(id, { readAt: Date.now(), pendingSync: true });
  });

  await mutationQueue.enqueue({
    kind: 'message.markRead',
    payload: { id, readAt: Date.now() },
    clientId: uuid(),
  });

  syncEngine.wake();
}
Enter fullscreen mode Exit fullscreen mode

Conflict resolution

  • Last-write-wins. Timestamps, newest wins. Fine for most consumer apps.
  • Server-authoritative. Reject stale writes with a version mismatch.
  • CRDTs. Yjs or Automerge. Overkill unless you're building a collaborative editor.

Decision cheat sheet

  • Preferences or JWT? → MMKV + expo-secure-store
  • Instant-open cached lists? → TanStack Query with persistQueryClient on MMKV
  • Thousands of offline records? → op-sqlite, or WatermelonDB if you want reactive
  • Cross-device sync? → WatermelonDB or Realm
  • Media? → expo-file-system with metadata in SQLite

Pitfalls to skip

  • Blocking the JS thread with async AsyncStorage calls at startup
  • Storing blobs in KV stores
  • No cache wipe on logout
  • Infinite retry loops in the mutation queue
  • Persisting Redux state without a schema version

Wrap-up

Offline-first isn't a defensive posture — it's a performance strategy. Reading from local storage beats a round-trip every time, and a good sync engine hides the network from your users entirely.

Pick each layer deliberately and this becomes a solved problem rather than a recurring one.


I built RapidNative, an AI mobile app builder that generates production-ready React Native code you can extend with any of these libraries.

Anyone running MMKV + TanStack Query in production? Curious how the persistence layer has held up for you at scale.

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

I found the discussion on the five categories of offline storage in React Native to be particularly insightful, especially the distinction between key-value stores like MMKV and secure enclaves like expo-secure-store. The performance difference between MMKV and AsyncStorage is striking, with MMKV being roughly 30× faster, which could significantly impact the user experience. The offline-first pattern outlined, with its four parts - local-first reads, optimistic writes, a durable mutation queue, and a sync engine - provides a comprehensive approach to handling offline storage. I'm curious to know more about how others have implemented the sync engine in their applications, particularly in terms of handling conflict resolution and exponential backoff.