iOS: UserDefaults
On iOS, expo-native-storage usesUserDefaults, Apple’s built-in key-value storage system.
Implementation
ExpoNativeStorageModule.swift
Characteristics
- Synchronous operations - All reads and writes execute on the calling thread
- Disk I/O - Writes persist to disk synchronously (~1ms per write)
- In-memory cache - UserDefaults maintains an in-memory cache for fast reads
- Thread-safe - Safe to access from any thread
- Automatic synchronization - Changes sync automatically across app extensions
Data size limits
Performance characteristics
- First write: ~1ms (disk I/O)
- Subsequent reads: <0.1ms (in-memory cache)
- Clear operation: Removes all keys for your app’s bundle ID
For bulk write operations (1000+ items), consider specialized libraries like react-native-mmkv which use memory-mapped files for faster disk I/O.
Android: SharedPreferences
On Android, expo-native-storage usesSharedPreferences, Android’s built-in key-value storage system.
Implementation
ExpoNativeStorageModule.kt
Characteristics
- In-memory cache - All data loads into memory on first access
- Asynchronous persistence -
apply()writes to disk asynchronously - Immediate reads - Reads return instantly from the in-memory cache
- Thread-safe - All operations are thread-safe
- Process-safe - Changes visible across app processes
Performance advantages
SharedPreferences performance improves with usage thanks to in-memory caching:| Operations | First Access | After Cache Load |
|---|---|---|
| 100 ops | ~12ms | <1ms |
| 500 ops | ~50ms | <5ms |
| 1000 ops | ~98ms | <10ms |
Data size considerations
Why it’s faster than AsyncStorage
expo-native-storage outperforms AsyncStorage on Android because:- In-memory caching - All data cached after first access
- No SQLite overhead - AsyncStorage uses SQLite which requires parsing, query execution, and result marshaling
- Optimized for key-value - SharedPreferences is purpose-built for key-value storage
Web: localStorage
On web platforms, expo-native-storage falls back to the browser’slocalStorage API.
Implementation
Characteristics
- Synchronous operations - All operations execute immediately
- String storage only - All values stored as strings
- Origin-scoped - Data isolated per origin (protocol + domain + port)
- Persistent - Data survives browser restarts
- No expiration - Data persists until explicitly cleared
Storage limits
Platform comparison
iOS
UserDefaults
- Synchronous disk I/O
- ~1MB per key recommended
- In-memory cache
- Thread-safe
Android
SharedPreferences
- In-memory cache
- Async disk writes
- Scales with usage
- Process-safe
Web
localStorage
- Synchronous
- 5-10MB per origin
- String storage
- Origin-scoped
Choosing the right storage solution
Use expo-native-storage for:
- User preferences and settings
- App configuration
- Small cached data
- Authentication tokens
- Feature flags
- Theme preferences
Consider alternatives for:
- Large files (images, videos) → Use
expo-file-system - Relational data → Use SQLite with
expo-sqlite - Bulk write operations (1000+ items) → Use
react-native-mmkv - Large JSON documents → Use a proper database
- Sensitive data → Use
expo-secure-storewith encryption
Next steps
Performance
Learn about performance benchmarks and optimization strategies.
Best Practices
Discover patterns for effective data management.