Gradle KTS is a Kotlin DSL for the Gradle build system that allows writing build scripts in Kotlin instead of Groovy. Files with the .gradle.kts extension support static typing, auto-completion in IntelliJ IDEA and Android Studio, as well as direct access to the Gradle API through Kotlin syntax. Google recommends KTS for Android projects starting with AGP 7.0, and Kotlin Multiplatform uses KTS as the standard configuration format. According to Gradle, 2025, over 60% of new projects choose KTS over Groovy for writing build scripts.
Key Takeaways
Gradle KTS is a Kotlin DSL (Domain Specific Language) that provides an alternative to Groovy for writing Gradle configuration files. Instead of Groovy syntax, developers use Kotlin — a strictly typed language that validates configuration correctness at compile time. KTS was first introduced in Gradle 5.0 in 2018 as an experimental feature and reached stability in Gradle 6.0.
The main goal of KTS is to eliminate the shortcomings of Groovy in build scripts. Groovy is a dynamically typed language where configuration errors only appear at runtime when executing a task. KTS allows detecting the same errors at the code editing stage thanks to Kotlin's static typing. Additionally, KTS provides access to the Gradle API with full type documentation, significantly simplifying learning and using complex configuration blocks.
The KTS ecosystem is supported by all major tools: Android Studio, IntelliJ IDEA, VS Code with the Kotlin plugin, and the Gradle Build Tool. All modern plugins (Android Gradle Plugin, Kotlin Multiplatform, Protobuf, Compose) provide a Kotlin-friendly API with explicit types, making KTS the preferred choice for new projects.
Gradle KTS uses the Kotlin compiler to process .gradle.kts files. Gradle recognizes the extension and passes the scripts to the Kotlin scripting engine, which compiles them into classes. These classes are then executed by Gradle to build the project model. The key difference from Groovy: KTS scripts are compiled ahead of time, not interpreted dynamically, allowing errors to be detected before task execution begins.
The KTS architecture is based on kotlin-scripting. Each .gradle.kts file is a Kotlin script with implicit imports of the Gradle API. The developer can use any Kotlin constructs: extension functions, lambdas, data classes, and even declare helper functions inside the build script. Gradle provides a set of extension functions for typed configuration of blocks: dependencies, android, kotlin, and others.
plugins {
id("com.android.application") version "8.4.0"
kotlin("android") version "2.0.21"
}
android {
namespace = "com.itsectr.app"
compileSdk = 34
defaultConfig {
applicationId = "com.itsectr.app"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
}
}
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.06.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.core:core-ktx:1.13.1")
}
One of the key differences between KTS and Groovy is type handling. In Groovy, all configurations accept Object, while in KTS they accept specific Kotlin types. For example, compileSdk accepts Int, not a string. This eliminates errors related to incorrect types: in Groovy, compileSdk 34 and compileSdk "34" work identically, while in KTS only the first variant is valid. This strictness makes configuration more predictable and documented.
Groovy was the original DSL for Gradle and remains fully supported. However, KTS offers several advantages that make it the recommended choice for new projects. Static typing, better IDE editing performance, and stricter syntax are the main reasons to switch to KTS. At the same time, Groovy retains its advantage in conciseness for simple configurations.
Build performance on KTS and Groovy is nearly identical after script compilation. KTS scripts take longer to compile on first run or after cache clearing, but subsequent builds run at the same speed as Groovy scripts. Gradle caches compiled KTS scripts in the build directory, so recompilation only happens when the script changes.
| Characteristic | Gradle KTS | Groovy DSL |
|---|---|---|
| Typing | Static, checked at compile time | Dynamic, checked at runtime |
| IDE support | Auto-completion + navigation + refactoring | Limited (dynamic typing) |
| Block syntax | Lambdas with receiver (typed) | Closure (untyped) |
| Property assignment | Using = (compileSdk = 34) | Without = sign (compileSdk 34) |
| First compilation | Slower (Kotlin compilation) | Faster (interpretation) |
| Subsequent builds | Identical (script cache) | Identical |
The choice between KTS and Groovy in 2026 is clear: for new projects — KTS. Google, JetBrains, and Gradle recommend KTS for all new projects. Groovy remains relevant for maintaining legacy projects where migration is impractical due to configuration volume or specific plugins incompatible with KTS.
Let's look at typical configuration blocks in KTS for Android, Kotlin Multiplatform, and Compose Multiplatform. An Android project with KTS requires explicit type specification in buildTypes and productFlavors configuration. The example below demonstrates setting up an application with two flavors.
android {
buildTypes {
val release = getByName("release") {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
getByName("debug") {
applicationIdSuffix = ".debug"
}
}
flavorDimensions += "version"
productFlavors {
register("demo") {
dimension = "version"
versionNameSuffix = "-demo"
}
register("full") {
dimension = "version"
}
}
}
For Kotlin Multiplatform, KTS is mandatory — Groovy does not correctly support the configuration of multiplatform modules. The KMM module configuration includes setting up target platforms and source sets. The example below shows the shared module configuration with iOS and Android.
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
sourceSets {
commonMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
}
androidMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
}
}
}
KTS allows declaring helper Kotlin functions inside the build script. This is especially convenient for repetitive configurations such as signing configs or version management. Thanks to static typing, such functions can be called with parameter validation at compile time, eliminating errors in signing configurations before publishing to Google Play.
fun Project.configureSigning() {
android {
signingConfigs {
register("release") {
storeFile = file("release.keystore")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
}
}
// Usage in build.gradle.kts
configureSigning()
Migration from Groovy to KTS is a process that can be done gradually. Gradle supports mixed projects where some modules use Groovy (build.gradle) and some use KTS (build.gradle.kts). The settings.gradle and root build.gradle can be migrated first since they don't depend on module plugins. Google recommends starting migration with settings.gradle.kts, then the root build.gradle.kts, and only then the modules.
The main migration steps include: replacing closure syntax with lambdas, adding = signs for assignment, replacing string keys with typed constants, and explicit variable typing. Android Studio provides automatic Groovy → KTS conversion for simple blocks, but complex configurations with nested closures require manual rewriting.
| Groovy (was) | KTS (became) |
|---|---|
| compileSdk 34 | compileSdk = 34 |
| buildTypes { release { ... } } | buildTypes { getByName("release") { ... } } |
| implementation 'com.android.x:y:1.0' | implementation("com.android.x:y:1.0") |
| flavorDimensions "version" | flavorDimensions += "version" |
| productFlavors { demo { ... } } | productFlavors { register("demo") { ... } } |
| def vsn = "1.0" | val vsn = "1.0" |
Typical migration issues include implicit Groovy method calls that have no Kotlin equivalent, and plugins that do not provide a Kotlin-friendly API. For the first issue, Gradle provides compatibility through withGroovyBuilder — a mechanism that allows calling Groovy methods from KTS. For the second — you need to wait for a plugin update or use it in a Groovy module until full migration.
Kotlin Multiplatform is the primary project where KTS is a mandatory requirement. The kotlin multiplatform plugin provides extensions for configuring target platforms, source sets, and framework binaries that are only available through Kotlin DSL. Groovy does not correctly support multiplatform configuration, so KMM projects exclusively use KTS.
KMM configuration in KTS includes non-standard blocks: kotlin.target for specifying platforms, kotlin.sourceSets for organizing common and platform-specific code, kotlin.cocoapods for CocoaPods integration, and kotlin.jvmToolchain for JDK selection. Each block has a strictly typed API with auto-completion in Android Studio, which is especially valuable for complex KMM project configuration with multiple platforms.
kotlin {
iosArm64()
iosSimulatorArm64()
iosX64()
cocoapods {
summary = "Shared Kotlin module"
homepage = "https://itsectr.com"
framework {
baseName = "Shared"
isStatic = false
}
pod("Alamofire") {
version = "5.9"
}
}
}
Thanks to KTS static typing, KMM developers get auto-completion for source sets and dependencies, type checking of framework configuration, and the ability to refactor platform names. KTS also simplifies debugging: errors in KMM configuration appear as Kotlin compilation errors with clear messages, unlike Groovy where errors could be hidden until a Gradle task is executed.
Frequently Asked Questions
It is mandatory for Kotlin Multiplatform projects. For Android and server projects, Groovy remains supported, but Google and Gradle recommend KTS for new projects due to static typing and better IDE support.
Yes, Gradle supports mixed projects. Each module can use its own DSL. The settings.gradle or settings.gradle.kts defines the root DSL, but modules are independent. This allows gradual migration.
KTS requires Kotlin compilation into bytecode before execution. This takes additional time on first run or after cache clearing. All subsequent builds use cached classes with speed comparable to Groovy.
Most modern plugins are compatible. Issues arise with outdated plugins that use a Groovy-specific API or Closure without a Kotlin equivalent. For such plugins, use withGroovyBuilder() or keep the module on Groovy.
After initial script compilation, build performance is identical to Groovy. Gradle caches compiled KTS scripts, and recompilation only occurs when they change. The difference in module build speed is negligible.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also