skip to content

What is the difference between languageVersion and apiVersion compiler options, and when would you set each?

level: middleimportance: should knowfreq 45%

answer

  1. languageVersion = syntax/features the compiler accepts
  2. apiVersion = which stdlib declarations you may call
  3. apiVersion <= languageVersion
  4. Both default to the compiler's own version
  5. Lower languageVersion to stage a compiler upgrade

basics

~10 s

languageVersion controls which Kotlin syntax/features the compiler accepts; apiVersion controls which version of the standard library you're allowed to call. You usually lower them to stay compatible with older consumers.

solid answer

~40 s

compilerOptions.languageVersion sets the version of the Kotlin language the compiler enforces — features newer than that version are reported as errors, letting you compile new-compiler code against older language semantics (source compatibility / a deprecation runway). compilerOptions.apiVersion restricts which kotlin-stdlib (and bundled library) declarations you may reference: APIs introduced after the chosen apiVersion are forbidden, so your artifact stays runnable against an older stdlib. They're independent: you can run Kotlin 2.x's compiler with languageVersion=2.0 and apiVersion=1.9, for example. apiVersion must be <= languageVersion. Both default to the compiler's own version. Common uses: library authors lowering apiVersion to support consumers on older stdlibs, or teams lowering languageVersion temporarily to ease a compiler upgrade before adopting new syntax.

go deeper

for a junior

Recognizes both exist and relate to Kotlin version compatibility, even if fuzzy on which is which.

for a middle

Clearly distinguishes language (syntax) from API (stdlib), knows apiVersion <= languageVersion and the defaults.

for a senior

Uses them to stage compiler upgrades and to keep a library compatible with older stdlibs on consumers' classpaths.

for a principal

Defines an org policy for version pinning across a library ecosystem, reasoning about N-1/N-2 support windows and binary compatibility.

## The two knobs Kotlin separates *which language you write in* from *which standard library you call*: - **`languageVersion`** — the version of the **Kotlin language** the compiler enforces. Source-level features (new syntax, new keywords, new semantics) added after this version are rejected with errors. Setting `languageVersion = 2.0` while using a 2.2 compiler means: "use the new compiler binary, but only let me write Kotlin-2.0 source." - **`apiVersion`** — the maximum version of the **Kotlin standard library / dependent libraries** whose declarations you're allowed to reference. Any stdlib function/class introduced *after* `apiVersion` is a compile error. This keeps the produced artifact runnable against an **older `kotlin-stdlib`** on the classpath. ```kotlin kotlin { compilerOptions { languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9) } } ``` ## Why they're independent You can mix them. A library that ships to consumers stuck on an old stdlib might use a brand-new compiler (for bug fixes/speed) but set `apiVersion = 1.9` so it never *links against* stdlib symbols those consumers lack. The rule: **`apiVersion` must be ≤ `languageVersion`** — you can't call APIs from a language version you've forbidden yourself from speaking. ## Defaults and the deprecation runway Both default to the **compiler's own version** (e.g. with the 2.2 compiler, both default to 2.2). The Kotlin team typically supports the current version and **N-1 / N-2** for these options. Lowering `languageVersion` is the standard way to **stage a compiler upgrade**: bump the Kotlin Gradle plugin (faster compiler, fixes) while temporarily pinning `languageVersion` to the old one, then drop the pin once the team adopts the new syntax. ## Contrast with jvmTarget - `jvmTarget` → JVM **bytecode** format. - `languageVersion` → Kotlin **source language** level. - `apiVersion` → Kotlin **stdlib API** surface you may use. These are three orthogonal dials.

  • Can apiVersion be higher than languageVersion?
    No. The compiler requires apiVersion <= languageVersion, because you cannot reference APIs from a language version you have disabled.
  • Why use a newer compiler with an older languageVersion?
    To get the new compiler's speed and bug fixes immediately while giving the team a runway to migrate source before adopting new language features.

saying these in an interview costs you the question

  • Saying languageVersion and apiVersion are the same thing
  • Confusing either with jvmTarget / bytecode level
  • Claiming apiVersion can exceed languageVersion
  • Thinking these change which JDK is used
  • Not knowing they default to the compiler's version

context