Room/SQLite is the right choice for most Android apps. But there are specific scenarios where alternative databases offer meaningful advantages. Here's an honest comparison.
Room/SQLite: The Default
Use Room unless you have a compelling reason not to. It's:
- Officially supported by Google
- Compile-time query verification
- Kotlin-native with Flow and coroutines
- Well-documented, widely understood
- No additional dependencies
Realm: Object-Oriented Mobile Database
Realm stores objects natively (no ORM mapping) and observes changes reactively with zero-copy reads from memory-mapped files.
// Realm: define schema as Kotlin class
class Article : RealmObject {
@PrimaryKey var id: String = ""
var title: String = ""
var body: String = ""
var publishedAt: Long = 0
}
// Write
realm.write {
copyToRealm(Article().apply {
id = "a1"; title = "Hello"; publishedAt = System.currentTimeMillis()
})
}
// Reactive query — live object
val articles: Flow<ResultsChange<Article>> = realm.query<Article>()
.sort("publishedAt", Sort.DESCENDING)
.asFlow()
Realm advantages:
- No mapping layer — objects are the database
- Zero-copy reads (memory-mapped file)
- Native reactive queries with object change detection
- Built-in device sync (Realm Sync / Atlas)
Realm disadvantages:
- Objects must extend
RealmObject(invasive) - Not standard SQL — can't use SQL tooling
- Larger APK size (~2–4 MB)
- Smaller community than Room
- Thread-confined objects (old API; managed/frozen objects in new Kotlin SDK)
When Realm makes sense:
- Real-time collaboration that needs Atlas Sync
- Very large object graphs where ORM mapping is a bottleneck
- You're already invested in Realm and find Room's SQL cumbersome
ObjectBox
ObjectBox is a high-performance object database designed for mobile:
@Entity
data class Article(
@Id var id: Long = 0,
var title: String = "",
var publishedAt: Long = 0
)
// Query
val articles = articleBox.query(Article_.publishedAt.greater(timestamp)).build().find()
ObjectBox advantages:
- Benchmarks show 5–10× faster than SQLite for simple lookups
- Native Kotlin support
- No SQL required
Disadvantages:
- Commercial license for some features
- Smaller ecosystem
- Not as well-known in Android community
DataStore: Not a Database, But Worth Mentioning
For small structured data (user preferences, settings, session tokens), DataStore is better than Room:
// Proto DataStore: typed preferences via Protocol Buffers
val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(
fileName = "user_prefs.pb",
serializer = UserPreferencesSerializer
)
// Preferences DataStore: untyped key-value
val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")
context.dataStore.edit { prefs -> prefs[DARK_MODE_KEY] = true }
val darkMode = context.dataStore.data.map { it[DARK_MODE_KEY] ?: false }
Decision Matrix
| Scenario | Recommended DB |
|---|---|
| Standard structured data, SQL queries | Room + SQLite |
| Simple key-value preferences, settings | DataStore |
| Need real-time server sync, collaboration | Realm + Realm Sync |
| Highest performance lookups, no SQL needed | ObjectBox (evaluate carefully) |
| Already using Firebase Firestore | Firestore local persistence |
Key Takeaways
- Room is the safe default — well-tested, supported, SQL-compatible
- Realm is compelling specifically for real-time sync with Atlas and object-oriented data models
- Don't switch databases for performance without profiling first — most Room performance issues are solved with proper indexes and transactions
- DataStore replaces
SharedPreferencesfor small structured preferences — it's not a general-purpose database