Kotlin 2.3.20 Lands Name-Based Destructuring, Gradle 9.3 Support, and a Rewired Kotlin/Wasm That Runs Up to 4.6x Faster
Kotlin 2.3.20 ships name-based destructuring, default Build Tools API on Kotlin/JVM, Gradle 9.3.0 compatibility, and Wasm string performance gains of up to 4.6 times.
Overview
JetBrains shipped Kotlin 2.3.20 on March 16, 2026, a point release that layers new language ergonomics, build-system plumbing, and performance work onto the 2.3 line that debuted in December 2025. According to the Kotlin project’s What’s New page, the release introduces experimental name-based destructuring declarations, flips Kotlin/JVM compilation to use the Build Tools API by default, extends Gradle compatibility to version 9.3.0, and delivers sizeable speedups to Kotlin/Wasm string handling and clean builds.
The JetBrains announcement lists the main highlights as Gradle 9.3.0 compatibility with Kotlin/JVM defaulting to the Build Tools API, simplified Maven setup, Lombok reaching Alpha with improved JPA support, name-based destructuring, a new immutable Map.Entry copy API, and a new C/Objective-C interop mode in Kotlin/Native.
What We Know
Name-based destructuring declarations
Kotlin 2.3.20 adds an experimental form of destructuring that matches variables to property names instead of the positional componentN() functions used since Kotlin 1.0. In the new syntax, a data class User(val username: String, val email: String) can be unpacked with explicit name bindings such as (val mail = email, val name = username) = user, according to the Kotlin documentation.
The feature ships behind the -Xname-based-destructuring compiler flag with three modes — only-syntax enables the explicit form without changing existing behavior, name-mismatch warns when variable names do not match properties, and complete turns on the short-form parenthesized syntax along with a new square-bracket syntax for position-based destructuring, per the Kotlin release notes. InfoWorld summarized the feature as letting developers “match variables to property names instead of relying on position-based componentN() functions.”
Kotlin/JVM switches to the Build Tools API by default
Kotlin/JVM compilation now uses the Build Tools API (BTA) by default, a shift JetBrains says will make it faster to add support for new build tools in the future, according to the Kotlin documentation. The BTA itself picks up cancellable build operations through a CancellableBuildOperation interface, consistent build-tool-agnostic metric collection across compiler execution strategies, and a simpler configuration API for compiler plugins, per the release notes.
Gradle 7.6.3 through 9.3.0 and simpler Maven setup
The release is compatible with Gradle 7.6.3 through 9.3.0, according to the Kotlin documentation. Binary compatibility validation tasks have been renamed from checkLegacyAbi/updateLegacyAbi to checkKotlinAbi/updateKotlinAbi, and checkKotlinAbi now runs automatically as part of Gradle’s standard check task, per the release notes.
Maven support graduates to stable: declaring the kotlin-maven-plugin with <extensions>true</extensions> now automatically registers src/main/kotlin and src/test/kotlin as source roots and adds the kotlin-stdlib dependency, according to the Kotlin documentation. The JetBrains blog lists the change simply as “Maven: Simplified setup for Kotlin projects,” per the Kotlin blog.
Lombok reaches Alpha, JPA plugin auto-applies all-open
The Kotlin Lombok compiler plugin moves from Experimental to Alpha, formalizing its role in mixed Kotlin/Java modules that rely on Lombok-generated code, according to the Kotlin documentation. The kotlin.plugin.jpa plugin now automatically applies the all-open compiler plugin with a built-in JPA preset, auto-annotating javax.persistence.Entity, Embeddable, and MappedSuperclass (and their jakarta.persistence equivalents) so lazy associations work without manual configuration, per the release notes.
Kotlin/Wasm string handling gets substantially faster
Kotlin/Wasm is one of the bigger performance stories in the release. Using JavaScript string builtins for kotlin.String operations delivers “up to 4.6 times faster string interpolation” and roughly 5 percent smaller Wasm binaries, along with a 20 percent speedup in StringBuilder.append(), according to the Kotlin documentation. The release also claims a 65 percent improvement in clean build times for Wasm projects and a 21 percent improvement for incremental builds, per the release notes.
An experimental @nativeInvoke annotation lets Kotlin objects and classes be treated as JavaScript functions, so an external class JsAction { @nativeInvoke operator fun invoke(data: String) } can be called as action("Run task") from the Kotlin side, according to the Kotlin documentation. A breaking change accompanies the Wasm work: module initialization now happens during instantiation rather than via a separate external _initialize() call, per the release notes.
New C and Objective-C interop mode in Kotlin/Native
Kotlin 2.3.20 introduces an experimental interoperability mode for C and Objective-C libraries aimed at fixing Kotlin Multiplatform compatibility issues when the same library is used across different Kotlin versions, according to the Kotlin documentation. Teams can opt in by setting -Xccall-mode=direct as an extra option on cinterop tasks in their Gradle configuration, per the release notes. A new crossCompilationSupported API lets build scripts check whether cross-compilation is feasible for a given target, and a DSL-level disableNativeCache replaces the deprecated kotlin.native.cacheKind Gradle property. InfoWorld frames the change as part of a broader push toward harmonizing Kotlin with C, JavaScript, and TypeScript.
Kotlin/JS: TypeScript interface implementation, standard library, annotations
Kotlin 2.3.20 removes a long-standing limitation on implementing Kotlin interfaces from the TypeScript side by introducing proper Symbol-based bridging, making it possible to write a TypeScript class JsonProcessor implements DataProcessor against a Kotlin-declared interface, according to the Kotlin documentation. InfoWorld describes the change as the release “lifting the limitation on implementing Kotlin interfaces on the JavaScript and TypeScript sides,” per InfoWorld. The release also ships experimental SWC Rust-based transpilation via the kotlin.js.delegated.transpilation=true Gradle property, an experimental Map.Entry.copy() API for immutable entry copies, Vert.x @Nullable support, and treatment of @Unmodifiable/@UnmodifiableView collections as read-only (warning in 2.3.20, error in 2.5.0), per the Kotlin documentation.
What We Don’t Know
Several of the headline features — name-based destructuring, the new C/Objective-C interop mode, @nativeInvoke, SWC transpilation, and the Map.Entry.copy() API — ship as experimental and sit behind explicit compiler flags or opt-ins, according to the Kotlin documentation. How quickly they stabilize, and whether the complete-mode destructuring syntax changes before it reaches stable status, remains open.
The release also deprecates experimental context receivers in favor of context parameters and marks macosX64, tvosX64, and watchosX64 Apple targets for removal in the next release, per the Kotlin documentation. How much disruption those deprecations cause in multiplatform projects, and whether the BTA migration produces noticeable regressions or improvements in real-world build times, will become clearer as the release sees broader adoption.