skip to content

You're adding Room to a Kotlin module. Which Gradle dependency configuration do you use to wire up Room's annotation processor, and what else must you add to the build?

level: juniorimportance: must knowfreq 70%

answer

  1. ksp(room-compiler), not implementation
  2. Apply the KSP Gradle plugin first
  3. room-runtime + room-ktx + ksp compiler
  4. Room generates *_Impl classes
  5. Room is KSP-native — prefer ksp over kapt

basics

~20 s

You add the Room library as a normal dependency, and put Room's compiler on the ksp configuration (the modern way) instead of a plain dependency. You also apply the KSP Gradle plugin so ksp(...) exists.

solid answer

~30 s

Apply the KSP plugin (com.google.devtools.ksp), then in dependencies use implementation("androidx.room:room-runtime") and the Kotlin extensions implementation("androidx.room:room-ktx"), and crucially ksp("androidx.room:room-compiler") so the compiler that generates the *_Impl DAO/database classes runs. Room ships native KSP support, so prefer ksp(...) over kapt(...). The ksp() configuration tells KSP which artifact contains the SymbolProcessorProvider; without the plugin applied, ksp(...) is unresolved. With kapt you'd instead apply org.jetbrains.kotlin.kapt and use kapt("androidx.room:room-compiler"), but that path is slower and discouraged for Room.

code

kotlin · 10 lines
kotlin
plugins {
    id("org.jetbrains.kotlin.jvm")
    id("com.google.devtools.ksp")
}

dependencies {
    implementation("androidx.room:room-runtime")
    implementation("androidx.room:room-ktx")
    ksp("androidx.room:room-compiler")
}

go deeper

for a junior

Knows the compiler goes on ksp(...) and that the KSP plugin must be applied.

for a middle

Explains why implementation() doesn't invoke the processor and that Room is KSP-native.

for a senior

Discusses generated-source wiring, room-ktx vs runtime split, and the kapt fallback tradeoff.

for a principal

Can reason about migrating a whole multi-module build off kapt and standardizing the KSP version via the version catalog/convention plugins.

## What Room needs at build time Room generates code (DAO implementations like `UserDao_Impl`, the database `_Impl`) from your `@Entity`, `@Dao`, and `@Database` annotations. That code is produced by an **annotation processor**, which must run during compilation. In Gradle you express "run this processor" by placing the processor artifact on a special dependency **configuration**. ## The two configurations - **`ksp(...)`** — Kotlin Symbol Processing. The modern, Kotlin-native processor API. Faster because it reads Kotlin source directly (no Java stubs). - **`kapt(...)`** — Kotlin Annotation Processing Tool. The legacy bridge that generates Java stubs so Java-based (`javax.annotation.processing`) processors run. Slower. Room **ships native KSP support**, so use `ksp(...)`. ## Required pieces 1. **Apply the KSP plugin** so the `ksp(...)` configuration exists: ```kotlin plugins { id("com.google.devtools.ksp") } ``` 2. **Add dependencies** — runtime as a normal dependency, compiler on `ksp`: ```kotlin dependencies { implementation("androidx.room:room-runtime") implementation("androidx.room:room-ktx") // coroutines/Flow support ksp("androidx.room:room-compiler") // the processor } ``` ## Why not just `implementation` for the compiler? If you put `room-compiler` on `implementation`, the processor jar lands on the runtime classpath but is **never invoked**, so no `_Impl` classes are generated and you get "cannot find implementation" errors. The configuration name is what activates the processor. ## kapt alternative (discouraged for Room) ```kotlin plugins { id("org.jetbrains.kotlin.kapt") } dependencies { kapt("androidx.room:room-compiler") } ``` This works but is slower. Prefer KSP.

  • What happens if you apply the KSP plugin but forget the ksp("androidx.room:room-compiler") line?
    The configuration exists but no Room processor is registered, so no DAO/database implementation classes are generated and the build fails with missing _Impl classes.
  • Where does the generated code end up?
    Under build/generated/ksp/<variant>/kotlin (or .../java), and KSP automatically adds it to the source set so it compiles.

ksp(...) is like a backstage pass: it lets the processor onstage to generate code; a plain dependency just leaves it in the audience.

saying these in an interview costs you the question

  • Putting room-compiler on implementation or api
  • Forgetting to apply the KSP (or kapt) plugin
  • Thinking ksp() and implementation() are interchangeable
  • Claiming Room requires kapt

context