How to use an existing database with an Android application
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Using an existing database in an Android app can mean two very different things: shipping a prepopulated SQLite database with the app, or connecting to a remote server database. Those cases should be handled differently, and confusing them leads to bad architecture quickly.
Use a Prepackaged SQLite Database for Offline Data
If the existing database is already SQLite and should live on the device, package it as an asset and copy or open it through Android's database layer. With modern Android, Room is usually the cleanest approach.
A Room setup with a prepackaged database looks like this:
This is much cleaner than manually copying files with streams unless you are maintaining older code that predates Room.
If your source database is not SQLite, convert it first. Android does not embed MySQL or PostgreSQL servers inside your app.
Use an API for Remote Databases
If the "existing database" is a server database such as MySQL or PostgreSQL, do not connect to it directly from Android. The usual design is:
- Android app talks to an HTTPS API
- API talks to the database
- app receives JSON or another controlled response format
A simple Retrofit example:
This protects credentials, centralizes validation, and avoids exposing the database directly to every mobile client.
Think About Updates and Migrations
If you ship a local database with the app, decide how it will be updated later. A prepackaged asset is great for seed data, but users may eventually need migrations when the schema changes.
With Room, schema versioning and migrations give you a safer path:
Then include it in the builder:
That keeps the packaged starting state and the installed database lifecycle aligned.
Common Pitfalls
The biggest mistake is trying to connect directly from Android to a production relational database server. That exposes credentials, expands the attack surface, and usually performs poorly on mobile networks.
Another common issue is assuming any existing database file can simply be dropped into an Android project. If it is not SQLite, it needs conversion or a server-side access layer.
People also manually copy prepackaged SQLite files even in new projects where Room already supports createFromAsset. Manual copy logic works, but it adds more code paths to test and maintain.
Finally, do not forget schema migrations. A preloaded database is only the starting point. Once users install the app, updates must preserve their local state correctly.
If the database is large, also think about app size and first-launch time. Shipping a huge asset may be less practical than syncing the needed data after installation.
Summary
- First decide whether the existing database is a local SQLite file or a remote server database.
- Use a prepackaged SQLite asset for offline local data on Android.
- Use an API, not a direct database connection, for remote server databases.
- Prefer Room and
createFromAssetfor modern Android local-database integration. - Plan schema migrations early so updates do not break installed apps.
Related reading
- How to use an existing database with an Android application
- How to use an init container to check if MySQL is ready for connections?
- How to use async Mysql query with PHP PDO
- How to use auto increment for primary key id in dynamodb
- How to use Android App as a client for Kafka?
- How to use Attributed String in SwiftUI
- How to use ClickHouse partition value in SQL query?
- How to use clickhouse WITH FILL function to fill non-order by column with previous value instead of 0?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.