Expo Realm vs Expo SQLite: A Practical, Developer-Centric Comparison for Expo Apps
1. Introduction: Local Databases in Expo – Why Realm and SQLite?
Modern Expo and React Native app builders face high demands: seamless offline support, fast data querying, and the ability to sync or scale as needs evolve. Most simple solutions (like AsyncStorage) hit limits as soon as you need relationships, data constraints, migrations, or fast search. That’s where Expo Realm and Expo SQLite stand out—one offering object/document-oriented local storage with powerful live queries and cloud sync, the other providing rock-solid SQL with familiar schema, transactions, and efficient queries.
This post delivers a practical lens on both tools—why you’d choose one or the other, and how to quickly get your project started with robust patterns and code.
Quick Decision Table:
| Feature | Realm | SQLite |
|---|---|---|
| Data Model | Object/NoSQL | SQL/Table |
| Live Reactivity | Built-in | Manual query |
| Cloud Sync | Yes (Atlas) | DIY |
| Reporting/Analytics | Less idiomatic | Excellent |
| Expo Go support | No | Yes |
(See [Section 9] for a full summary matrix and checklist.)
2. Expo Realm: Installation, Setup, and Project Integration
Realm delivers fast, ACID-compliant, object data stores with automatic reactivity and deep relationship support. But due to native code dependencies, Expo projects require a few extra setup steps—especially for managed workflow.
Install in Expo (Managed, with expo-dev-client):
Sh
- Use EAS Build for production/release (see official EAS Docs).
Schema & Provider:
Js
- Use React hooks (
useRealm,useQuery) for all data access (see detailed CRUD in Section 4).
Troubleshooting:
- Realm requires expo-dev-client or bare workflow (does not work in basic Expo Go).
- For model changes, increment
schemaVersionand provideonMigration. - See official compatibility table for Expo/Realm/React Native versions.
3. Expo SQLite: Installation, Integration, and Workflow Compatibility
SQLite is the default, frictionless relational database for Expo, supported fully in managed (Expo Go/EAS) and bare workflows.
Install:
Sh
- No custom dev-client/ejecting required.
Basic Usage:
Js
- All CRUD involves explicit SQL and transactions (see Section 5 for code and best practices).
- Works out of the box with Expo Go, EAS Build, and all release workflows.
Integration Tips:
- Store file paths with expo-file-system for backup/restore.
- Use state management (React state, Redux) to refresh UI after data changes.
4. Data Modeling and CRUD Operations: Expo Realm in Practice
- Modeling: Use JavaScript classes for object schemas (examples in Section 4).
- CRUD with Hooks:
Js
- Live reactivity: UI auto-updates as soon as database changes.
- Relationships: Direct object refs and arrays (
taskson aProject). - Migrations: Bump
schemaVersion, supply migration callback.
See official examples and DennyWanye's Expo Realm Guide.
5. Data Modeling and CRUD Patterns: Expo SQLite in the Real World
- Schema: Defined through
CREATE TABLESQL statements. - CRUD: All with SQL, e.g.
Js
- Join and Relations: Via foreign keys, manual JOINs.
- Migration: Use
ALTER TABLE ...and version check on app load. - State & UI: Read fresh data into React state after every mutation.
Example projects:
6. Advanced Features, Cloud Sync, and Limitations
Realm Advanced:
- Live queries, deep relationships, offline-first sync via MongoDB Atlas, built-in encryption, native performance.
- Limits: Not usable in Expo Go, native-only, migration necessary for schema changes.
SQLite Advanced:
- Full SQL: aggregations, JOINs, indexing, batch operations, FTS (full text search)
- Third-party wrappers: expo-sqlite-orm, WatermelonDB.
- Limits: No built-in live queries; migrations are manual.
7. Real-World Case Studies: Projects and Patterns
- Realm: Collaborative notes, offline-first CRMs (see realm/realm-examples).
- Architecture:
RealmProviderat root, live hooks, cloud sync optional. - Pattern: Hooks and services for all CRUD, JSON export for portability.
- Architecture:
- SQLite: Field data loggers, reporting/analytics trackers.
- Pattern: Service modules, scheduled data flush/batch, state refresh after write.
- Use SQLite for dashboard-style apps or high-volume, analytics-rich data.
8. Migration, Integration, and Multi-Database Patterns
- Migration Steps: Export to JSON/CSV, map/transform, batch insert into new engine.
- Hybrid Apps: Store primary data in Realm; logs/analytics in SQLite (or vice versa).
- Scripts/Utilities: Use expo-file-system for transfers; example Node/Expo code in Section 8.
- Community references: expo-sqlite-orm, Realm migration docs
9. Conclusion, Choosing the Right Tool, and Resources
| Feature/Need | Expo Realm | Expo SQLite |
|---|---|---|
| Live sync/reactivity | ✔️ (object, hook-based) | Manual, polling |
| SQL/analytics | Less convenient | ✔️ (with joins & aggregations) |
| Expo Go support | Needs custom dev client | ✔️ (default) |
| Migrations | Built-in and tested | Manual or ORM |
| Encryption | Built-in | Not by default |
| Analytics/legacy SQL | Convert or hybridize | ✔️ |
Actionable checklist:
- Need Expo Go simplicity? → SQLite
- Will your app sync/collaborate in real time? → Realm
- SQL familiarity or deep analytics? → SQLite
- Multiple data layers (e.g., logs + objects)? → Run both, with clear code separation and migration utilities.






