SQLite database setup in mobile app

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
SQLite database setup in mobile app
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1050
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

SQLite Database Setup in Mobile Applications

SQLite built into iOS and Android at OS level. Question not whether to connect it — it's already there. Question is how to work with it so in six months you don't rewrite everything due to tangled raw queries or crashes from SQLiteDatabaseLockedException on Android.

ORM/Abstraction Choice

Working with SQLite directly via android.database.sqlite.SQLiteDatabase or sqlite3 on iOS is option for minimal scenarios. In real projects use ORM:

Platform Library Approach
Android Room (Jetpack) annotations + DAO
iOS GRDB.swift typesafe queries in Swift
Flutter sqflite + drift codegen + reactive
React Native react-native-sqlite-storage / op-sqlite raw SQL or TypeORM
Multiplatform SQLDelight shared SQL schema for iOS+Android

Room is Android standard, Google votes for it. GRDB.swift on iOS gives typesafe queries without extra magic. SQLDelight interesting for KMM projects: single .sq file with SQL, generates Kotlin and Swift code.

Room on Android: Right Architecture

@Entity(tableName = "products",
    indices = [Index(value = ["category_id"]), Index(value = ["sku"], unique = true)]
)
data class ProductEntity(
    @PrimaryKey val id: String,
    @ColumnInfo(name = "category_id") val categoryId: String,
    val sku: String,
    val title: String,
    @ColumnInfo(name = "price_cents") val priceCents: Int,
    @ColumnInfo(name = "updated_at") val updatedAt: Long,
    @ColumnInfo(name = "is_deleted") val isDeleted: Boolean = false
)

@Dao
interface ProductDao {
    @Query("SELECT * FROM products WHERE category_id = :categoryId AND is_deleted = 0 ORDER BY title ASC")
    fun observeByCategory(categoryId: String): Flow<List<ProductEntity>>

    @Upsert
    suspend fun upsert(products: List<ProductEntity>)

    @Query("UPDATE products SET is_deleted = 1, updated_at = :timestamp WHERE id = :id")
    suspend fun softDelete(id: String, timestamp: Long)
}

@Upsert appeared in Room 2.5 — before that needed @Insert(onConflict = OnConflictStrategy.REPLACE). Soft delete via is_deleted flag — standard practice for synced DBs to not lose record before server confirmation.

Migrations — Most Painful Place

Room checks exportedSchema on schema change. If fallbackToDestructiveMigration() — DB recreates on every schema change. Fine for debug, unacceptable for production.

val db = Room.databaseBuilder(context, AppDatabase::class.java, "app.db")
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3)
    .build()

val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE products ADD COLUMN tags TEXT NOT NULL DEFAULT ''")
        db.execSQL("CREATE INDEX IF NOT EXISTS index_products_updated_at ON products(updated_at)")
    }
}

Export schema to JSON (room.schemaLocation in build.gradle) and commit to git. Code review instantly shows schema changes. Room can auto-generate migration for simple cases (add column) via AutoMigration, but table/column rename needs @RenameTable/@RenameColumn annotations.

GRDB.swift on iOS

// Open and configure
let dbQueue = try DatabaseQueue(path: dbPath)

try dbQueue.write { db in
    try db.create(table: "products", ifNotExists: true) { t in
        t.primaryKey("id", .text)
        t.column("category_id", .text).notNull().indexed()
        t.column("sku", .text).unique()
        t.column("title", .text).notNull()
        t.column("price_cents", .integer).notNull()
        t.column("updated_at", .integer).notNull()
    }
}

// Reactive observation via ValueObservation
let observation = ValueObservation.tracking { db in
    try Product.filter(Column("categoryId") == categoryId).fetchAll(db)
}
let cancellable = observation.start(in: dbQueue,
    onError: { error in print(error) },
    onChange: { products in self.updateUI(products) }
)

ValueObservation — like Room's Flow: auto-reruns query on affected table changes.

WAL Mode and Performance

SQLite runs in journal mode by default. For mobile apps, WAL (Write-Ahead Logging) better: readers don't block writers. Room enables WAL automatically. In GRDB: dbQueue.configuration.journalMode = .wal.

Typical problem — N+1 query in RecyclerView. SELECT * FROM orders returns 200 rows, then for each SELECT * FROM order_items WHERE order_id = ?. 200 queries on UI thread — ANR in 5 seconds on real device. Solution: JOIN or separate batch query WHERE order_id IN (...).

Setup SQLite with Room or GRDB, migration strategy, indexes: 1 week on one platform. Cost estimated individually.