How to Choose a Mobile Database: SQLite, Realm, Room and WatermelonDB

How to Choose a Mobile Database: SQLite, Realm, Room and WatermelonDB

Most database decisions get made in about eleven minutes, usually by whoever scaffolds the project. Then the app grows to 40,000 local records, the list starts stuttering on mid-range Android, and that eleven-minute decision costs a six-week rewrite.

Nobody intends to pick badly. They just pick before knowing what the app will actually have to do.

TL;DR

  • How you choose a mobile database comes down to four things: offline needs, data shape, dataset size, and your team’s existing stack.
  • SQLite and Room are the safe default for structured, relational data on Android and native apps.
  • Realm wins on raw read speed and object modeling. WatermelonDB wins on large lists in React Native through lazy loading.
  • EngineerBabu benchmarks the local data layer against projected record volumes before writing feature code, which is where most mobile rewrites get avoided.

The short version

When you choose a mobile database, you are picking a local storage engine that lives inside the app and keeps working when the network does not. The four realistic options are SQLite, Room, Realm, and WatermelonDB.

SQLite is the raw relational engine. Room is Google’s typed wrapper over SQLite. Realm is an object database with its own storage engine. WatermelonDB is a reactive layer built on SQLite, designed for React Native apps with heavy data.

Demand for this category keeps climbing. The embedded database system market is expected to reach US$ 23.55 billion by 2034, up from US$ 11.71 billion in 2025, at an 8.08% CAGR, per The Insight Partners.

Four questions to answer before you choose a mobile database

  • How offline does the app need to be?

A news reader that caches twenty articles has different needs than a field inspection app used in basements with no signal. The second one needs conflict resolution, a sync queue, and a schema that tolerates stale writes.

Be honest about which one you are building. Offline-capable and offline-first are not the same product.

  • How relational is your data?

Count the joins. If your domain has invoices with line items, customers, and tax rules, you want SQL. If your domain is a flat list of objects with nested properties, an object database maps more cleanly.

Forcing deeply relational data into an object store produces manual join code that nobody wants to maintain.

  • How large will the local dataset get in year two?

Three hundred rows behaves identically everywhere. Three hundred thousand does not. Ask what the heaviest user looks like after eighteen months, then test against that number, not against seed data.

  • What does your team already know?

A Kotlin team shipping with Kotlin app development patterns will be productive in Room on day one. A React Native team will not. The cost of unfamiliar tooling shows up as bugs, not as calendar time.

SQLite: the default that is genuinely hard to beat

SQLite ships inside both Android and iOS development. It is the most deployed database engine in the world, it has no server, no license cost, and no runtime dependency to manage.

You write SQL. You get full relational power, transactions, indexes, and a file format that will still open in fifteen years.

  • Pick it when: your data is relational, you want zero dependencies, or you need full control over query plans.
  • Skip it when: your team will end up writing a homegrown ORM, which is a project in itself.

The one real complaint is boilerplate. Raw cursor handling and manual mapping get tedious quickly in Android app development, which is exactly the problem Room was built to solve.

Room: SQLite with guardrails

Room is Google’s persistence library sitting over SQLite. You define entities as data classes and DAOs as interfaces, and Room validates your SQL at compile time.

That compile-time check is the headline feature. A typo in a column name fails the build instead of crashing in production.

  • Pick it when: you are building native Android, especially with Kotlin coroutines or Flow.
  • Skip it when: you need the same data layer shared across iOS and Android, because Room is Android only.

Room also integrates cleanly with Paging 3 for large lists, and plays well with WorkManager when you sync through an API development layer in the background.

Realm: object-first and very fast

Realm stores objects directly rather than mapping rows to classes. There is no ORM translation step, which is why reads often land noticeably faster than SQLite for object graphs.

Live objects are the standout feature. Query results update automatically when the underlying data changes, so your UI stays in sync without manual refresh logic.

  • Pick it when: your data is object-shaped, you want reactive queries out of the box, or you need one data layer across iOS and Android.
  • Skip it when: your schema is deeply relational or your app is size-sensitive, since the Realm runtime adds several megabytes.

Two caveats matter. Realm is now under MongoDB, and the Atlas Device Sync service was deprecated, so plan your own sync path. Also, Realm objects are thread-confined, which trips up teams new to it.

WatermelonDB: built for big lists in React Native

WatermelonDB is not a storage engine. It is a reactive layer over SQLite designed for one specific pain: React Native apps where a huge local dataset makes the JS bridge the bottleneck.

Its trick is lazy loading. Nothing gets read from disk until a component actually subscribes to it, so a 50,000-record table does not block your launch screen.

  • Pick it when: you are building React Native with tens of thousands of local records and a sync protocol you control.
  • Skip it when: your app holds a few thousand records, where the added complexity buys you nothing.

Teams comparing options here often weigh it alongside the trade-offs in Ionic vs React Native, since the data layer choice is downstream of the framework choice.

Side by side

SQLite Room Realm WatermelonDB
Model Relational Relational Object Relational, reactive
Platforms All Android only iOS, Android, RN React Native, web
Query style Raw SQL SQL + DAO Object queries Query builder
Reactive No Yes, via Flow Yes, live objects Yes, observables
App size impact Near zero Minimal 4 to 10 MB Small
Best at Control Type safety Read speed Huge lists

Matching the database to the product

App type Reasonable pick
Native Android, relational data Room
Native iOS, object-shaped data Realm
Cross-platform with shared models Realm
React Native, heavy local data WatermelonDB
Simple cache or key-value needs SQLite, or skip the database

That last row matters more than people expect. Not every app needs a database. If you are storing a token and three user preferences, DataStore or MMKV will do the job in a fraction of the code.

Planning for schema changes before you ship

Migrations are where mobile databases get painful, because you cannot force every user onto the new version at once. Older app builds stay installed for months.

Write your first migration before you ship version one, even if it only bumps the version number. It forces the path to exist. Room generates migration stubs and fails loudly on a missing one, which is better than silent data loss.

Realm handles additive changes automatically but needs a migration block for renames and type changes. Test every migration against a copy of a real production database file, not a freshly seeded one.

Mistakes worth avoiding

  • Benchmarking with toy data. Two hundred seeded rows tell you nothing. Load the volume you expect in year two and measure cold start.
  • Treating the local database as a cache of the server. Offline-first means the local store is the source of truth and the server reconciles. Build sync around that, not the reverse.
  • Storing sensitive data unencrypted. SQLCipher or Realm’s built-in encryption should be decided upfront, especially for anything following the rules around a HIPAA compliant app.
  • Running queries on the main thread. It works in development and freezes the UI in the field.

Final thoughts

There is no universally correct answer here. You choose a mobile database the same way you choose any other architectural component, by naming your constraints first and letting them narrow the list.

Relational data on Android points to Room. Object graphs across both platforms point to Realm. Enormous local datasets in React Native point to WatermelonDB. Everything else usually points back to plain SQLite, which has survived twenty-five years of this exact debate.

Make the call with your year-two data volume in mind and the decision tends to hold. If you want a second opinion before you commit, EngineerBabu can benchmark the options against your actual schema.

FAQs

  • Is SQLite still a good choice in 2026?

Yes. It remains the most widely deployed database engine on mobile, costs nothing, adds no dependency, and handles relational data well. Most alternatives are wrappers or layers built on top of it.

  • Is Realm faster than SQLite?

For object reads, usually yes, because Realm skips the ORM mapping step. For complex relational queries with multiple joins, SQLite often performs better. The answer depends entirely on your data shape.

  • Can I use Room on iOS?

No. Room is Android only. If you need a shared data layer across both platforms, Realm or raw SQLite through a shared layer are the realistic options.

  • When does WatermelonDB make sense over plain SQLite in React Native?

When you are holding tens of thousands of local records and the bridge becomes your bottleneck. Below roughly five thousand records, the extra setup rarely pays for itself.

  • How do I handle sync between the local database and my backend?

Build a change queue with timestamps or version vectors, define a conflict resolution rule, and sync incrementally rather than in full. Realm’s managed sync service was deprecated, so most teams now implement this themselves.