---
name: android-room-database
description: "Room ORM scaffolds: entities, DAOs, migrations, Flow queries, type converters, instrumentation tests. Generates production-ready Room schemas with auto-migration, paging integration, and the test harness most apps skip."
license: MIT
---

# Android Room Database

Scaffolds a complete Room persistence layer for Kotlin Android apps: entities, DAOs, the database class, type converters, schema-versioned migrations, and the instrumentation tests teams usually leave out. Built around KSP (not kapt) and reactive `Flow` queries, it targets developers who want a production-shaped data layer instead of a half-wired `@Entity` and a single `getAll()`.

## When to use it

- Standing up the storage layer for a new feature module and you want DAOs, converters, and a `RoomDatabase` subclass wired together correctly the first time.
- Adding a column or table and you need a real `Migration` plus a `MigrationTestHelper` test so the upgrade doesn't crash on existing installs.
- Wiring Paging 3 into a list screen via `PagingSource` from a DAO query.
- Replacing `LiveData` plumbing with `Flow`-returning queries that emit on every relevant write.

## What it does

It generates `@Entity` classes (with `@PrimaryKey`, `@ColumnInfo`, `@Index`, `@ForeignKey`), `@Dao` interfaces using `@Query`/`@Insert(onConflict = …)`/`@Update`/`@Upsert`/`@Delete`, and a `@Database` class listing entities and `version`. Reactive reads return `Flow<List<T>>` or, for paging, `PagingSource<Int, T>`. `@TypeConverter` classes handle `Instant`, enums, and JSON-backed fields.

For migrations it emits both styles: explicit `Migration(n, n+1)` objects with `db.execSQL(...)`, and `@Database(autoMigrations = [AutoMigration(from, to)])` with `@RenameColumn`/`@DeleteColumn` specs where a column rename can't be auto-detected. It enables `exportSchema = true` and points KSP at a `schemas/` directory so each version's JSON is committed.

The test harness is the differentiator: a `MigrationTestHelper` instrumentation test that creates the DB at an old version, inserts rows, runs the migration, and asserts the data survived — plus in-memory `Room.inMemoryDatabaseBuilder` tests for DAO behavior.

## Usage

```kotlin
@Dao
interface TaskDao {
    @Query("SELECT * FROM task ORDER BY due_at")
    fun observeAll(): Flow<List<Task>>

    @Query("SELECT * FROM task WHERE done = 0")
    fun pendingPaged(): PagingSource<Int, Task>

    @Upsert suspend fun upsert(task: Task)
}
```

```kotlin
// build.gradle.kts
ksp { arg("room.schemaLocation", "$projectDir/schemas") }
```

## Tips & gotchas

- Use KSP, not kapt — Room's kapt processor is effectively deprecated and slower. The skill assumes `com.google.devtools.ksp` is applied.
- Commit the exported `schemas/*.json`. `MigrationTestHelper` reads them, and without them `room.schemaLocation` warnings become migration-test failures.
- Auto-migrations can't infer a column rename or a non-null column with no default — supply an `AutoMigrationSpec` or fall back to a manual `Migration`.
- A `Flow` query re-emits on any write to a table it touches, including unrelated rows. Scope queries and use `distinctUntilChanged()` to avoid redundant recompositions.

## FAQ

**Auto-migrations or manual migrations?** Auto for additive changes (new table, new nullable column). Manual for renames, type changes, or data backfills. The skill generates the matching test either way.

**Does it support KMP?** It targets Android Room. Room's multiplatform artifacts exist but the generated instrumentation tests assume an Android test runner.

**Why do my migration tests fail with "no such file"?** The `schemas/` JSON for the starting version isn't on disk — re-run a build at that version or commit the exported schema.
