kotlinx.coroutines: the standard coroutine runtime for Kotlin, module by module
Library support for Kotlin coroutines
At a glance
- What is it?
- kotlinx.coroutines is the JetBrains library that gives Kotlin structured concurrency, Flow, channels and dispatchers across JVM, Android, JS, Wasm and Native. This review covers what each module does, how to add it with Gradle, and where it stops being the right tool.
- Who is it for?
- Adopt kotlinx.coroutines if you are writing Kotlin and need structured concurrency, Flow or channels; the README treats the Kotlin 2.2.20 companion release as the supported pairing, so check your Kotlin version before upgrading. Do not adopt it as a general-purpose async framework for Java-only or Python services, and do not expect the README to document rollback or migration steps; that detail lives in CHANGES.md and docs/topics/compatibility.md.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What kotlinx.coroutines solves, and who ends up depending on it
Kotlin ships the suspend keyword and the compiler machinery for coroutines, but it does not ship a runtime for them. kotlinx.coroutines is that runtime. The README describes it as "Library support for Kotlin coroutines" with multiplatform support, and lists the builders, dispatchers, stream types and synchronization primitives that a Kotlin application needs once it writes its first suspend function.
That makes the audience broader than it first appears. Anyone writing Android UI code, JVM services, Kotlin/JS front ends or Kotlin/Wasm code who wants to avoid blocking a thread while waiting on I/O is in scope. The library is also the substrate other JetBrains libraries build on, which is why the module list is long: core, test, debug, reactive, ui, integration, plus a BOM for version alignment. The core module alone covers launch and async builders returning Job and Deferred, the Dispatchers object, delay and yield, Flow, Channel, Mutex and Semaphore, the scope builders coroutineScope, supervisorScope, withContext and withTimeout, and the select expression.
The project is not archived and its last push was on 2026-09-21. The most recent release listed is 1.11.0 from 2026-05-08, preceded by two release candidates in April 2026. The README states that this is a companion version for the Kotlin 2.2.20 release, which is the version constraint that matters most in practice.
How the modules fit together: core, platform splits and the rest
The architecture is a small common core with platform-specific additions layered on top. kotlinx-coroutines-core is described as "common coroutines across all platforms", so the builders, Flow, channels and scope functions live there and compile for every target. Everything platform-shaped is split out.
On Kotlin/JVM, core/jvm adds Dispatchers.IO for blocking work, the Executor.asCoroutineDispatcher extension for custom thread pools, and integrations with CompletableFuture. On Kotlin/JS and Kotlin/Wasm/JS, core/web adds Promise.await and a promise builder; core/js adds Window.asCoroutineDispatcher. Dispatchers.Main is the interesting case: the README notes it is available for Android, Swing and JavaFX only when the corresponding artifacts are present at runtime, while Darwin support is included out of the box. That asymmetry is worth remembering, because a missing Main dispatcher artifact produces a runtime failure rather than a compile error.
The remaining modules are opt-in. kotlinx-coroutines-test provides Dispatchers.setMain to override the main dispatcher in tests plus runTest and TestScope. kotlinx-coroutines-debug provides DebugProbes to probe, track, print and dump active coroutines, a CoroutinesTimeout rule that dumps coroutines on test timeout, and automatic integration with BlockHound. The reactive module bridges Reactive Streams, Flow on JDK 9, RxJava 2.x and 3.x, and Project Reactor. The ui module supplies Main dispatchers for Android, JavaFX and Swing. The integration module covers Guava ListenableFuture.await, Google Play Services Task.await and SLF4J MDC via MDCContext. Each of those is a separate dependency, so a project pays only for the surface it actually uses.
Adding kotlinx.coroutines with Gradle or Maven
The README gives Maven and Gradle instructions. For Gradle with the Kotlin DSL, the dependency and the Kotlin plugin version are declared together, and mavenCentral() must be in the repository list. The README also shows the Groovy DSL form of the plugin id for build.gradle.
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
}
plugins {
kotlin("jvm") version "2.2.20"
}
repositories {
mavenCentral()
}For Maven, the same artifact appears as a dependency element with groupId org.jetbrains.kotlinx and artifactId kotlinx-coroutines-core, and the README pairs it with a kotlin.version property set to 2.2.20.
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.11.0</version>
</dependency>
<properties>
<kotlin.version>2.2.20</kotlin.version>
</properties>On Android, the README says to add the kotlinx-coroutines-android module as well, since that is the artifact carrying the Main dispatcher for the platform. The README's own first example is a suspend main that launches a child coroutine, delays one second, prints "Kotlin Coroutines World!", and prints "Hello" from the outer scope; the guide at kotlinlang.org/docs/coroutines-guide.html is labelled "read it first" for a reason, because the API surface is large enough that the README is not a tutorial.
The test and debug modules are where most teams first hit friction
Two modules deserve separate attention because they change how you write code rather than what you can express.
kotlinx-coroutines-test exists because wall-clock delays and a real Main dispatcher make tests slow and flaky. Dispatchers.setMain lets a test substitute the main dispatcher, and runTest with TestScope lets suspending functions and coroutines be exercised under the test's own scheduler. The trade-off is that code which hardcodes a dispatcher or reaches for a real clock will not benefit, and the test module's behaviour is one more thing to keep aligned with the core version.
kotlinx-coroutines-debug is the answer to the most common complaint about coroutine-based code: a stack trace that shows a suspended continuation rather than a useful call path. DebugProbes can probe, keep track of, print and dump active coroutines, and CoroutinesTimeout dumps them automatically when a test times out. The README also notes automatic integration with BlockHound, which detects blocking calls on threads that should not block. Both are diagnostic tools, not correctness tools: they tell you what is running, not whether the design is sound. Expect to add them temporarily during an investigation rather than leave them in a production path, since their purpose is inspection of live coroutine state.
Where kotlinx.coroutines is the wrong dependency
The clearest boundary is language. This is a Kotlin library with multiplatform support; it is not a general async runtime you drop into a Java-only or Python codebase. A Java service that wants non-blocking I/O should look at its own ecosystem first, even though the JVM module interoperates with CompletableFuture.
The second boundary is the version pairing. The README states that 1.11.0 is a companion version for the Kotlin 2.2.20 release. That phrasing signals a coupling: the library tracks compiler and standard library releases, so a project pinned to an older Kotlin version cannot simply take the newest coroutines artifact. The README does not document rollback or a downgrade procedure, and it does not spell out what happens if you mismatch versions; the compatibility policy is deferred to docs/topics/compatibility.md and the change log to CHANGES.md. If you are upgrading, those two files are the ones to read, not the README.
The third boundary is Dispatchers.Main. Because Android, Swing and JavaFX require the corresponding artifacts at runtime while Darwin is included out of the box, a multiplatform project can compile cleanly and still fail on one target at runtime. That is a packaging problem more than a library problem, but it is one the type system will not catch for you.
kotlinx.coroutines compared with RxJava and Project Reactor
The honest comparison is not coroutines versus reactive streams, because kotlinx.coroutines ships the reactive module precisely to bridge them. The reactive module provides builders and iteration support for Reactive Streams, Flow on JDK 9, RxJava 2.x and 3.x, and Project Reactor, with names like Publisher.collect, Publisher.awaitSingle, rxFlowable, rxSingle, flux and mono.
The difference is in the programming model. RxJava and Reactor express asynchronous pipelines as operator chains over observable types, and their error and cancellation semantics are defined by those types. kotlinx.coroutines expresses the same work as ordinary-looking sequential code inside suspend functions, with structured concurrency deciding when a scope completes and what happens to children when it fails. Flow is the streaming half of that model: the README describes it as a cold asynchronous stream with a flow builder and an operator set including filter and map, which is close enough in spirit to a reactive stream that the bridge module exists.
So the practical question is which model your team already reasons in. If a codebase is built around Reactor's operators and its scheduler model, adding coroutines alongside it means maintaining two mental models and paying for the bridge at each boundary. If the codebase is Kotlin-first and wants suspend functions to look like blocking code, kotlinx.coroutines is the natural centre and the reactive module is the adapter rather than the foundation.
Maintenance, versioning and the Apache-2.0 licence
The repository is not archived and its last push was on 2026-09-21, so the project is being worked on. The release history visible here shows a deliberate cadence: 1.11.0-rc01 on 2026-04-15, 1.11.0-rc02 on 2026-04-27, and the final 1.11.0 on 2026-05-08. Release candidates before finals mean an upgrade path that lets you test early, and it also means the artifact you pin in production should be the final version rather than an rc.
The upgrade cost is dominated by the Kotlin pairing, not by API churn you can measure from the README. The repository carries both CHANGES.md and a separate CHANGES_UP_TO_1.7.md, plus KOTLIN_UPGRADE.md and docs/topics/compatibility.md, which suggests the maintainers treat Kotlin version transitions as a documented event rather than a footnote. There is also a kotlinx-coroutines-bom module in the repository layout, which is the mechanism for keeping the core, test, debug and platform artifacts on one version instead of listing each explicitly.
The licence is Apache-2.0, stated in the README badge and present as LICENSE.txt at the repository root, with a license/ directory alongside it. Apache-2.0 is a permissive licence that includes an explicit patent grant and requires attribution and notice retention; it is not a copyleft licence. Nothing here is legal advice, and if you redistribute the library or modify it, read LICENSE.txt rather than a badge.
Editorial conclusion
Adopt kotlinx.coroutines if you are writing Kotlin and need structured concurrency, Flow or channels; the README treats the Kotlin 2.2.20 companion release as the supported pairing, so check your Kotlin version before upgrading. Do not adopt it as a general-purpose async framework for Java-only or Python services, and do not expect the README to document rollback or migration steps; that detail lives in CHANGES.md and docs/topics/compatibility.md. Verify first that you have mavenCentral() in your repositories and that your Android build pulls kotlinx-coroutines-android rather than the core artifact alone.
Frequently asked questions
What is kotlinx.coroutines?
It is JetBrains' library support for Kotlin coroutines, with multiplatform support, and the README describes version 1.11.0 as a companion version for the Kotlin 2.2.20 release. It supplies the runtime pieces Kotlin's suspend keyword does not: builders, dispatchers, Flow, channels and scope functions.
What are coroutines?
The README does not define the concept; it points to the Guide to kotlinx.coroutines by example at kotlinlang.org/docs/coroutines-guide.html and marks it as the thing to read first. What the README does show is a suspend main that launches a child coroutine, delays one second and prints a message while the outer scope prints another.
Why use coroutines instead of threads?
The README does not make that argument directly. What it documents is that coroutines are launched with builders that return Job and Deferred, that Dispatchers.Default is provided for background coroutines, and that Dispatchers.IO exists on the JVM for blocking work, which is where thread management is handed to dispatchers rather than to manual thread creation.
Why is a coroutine lightweight?
The README does not explain the weight of a coroutine. It documents the mechanism instead: launch and async return Job and Deferred, which it calls light-weight futures with cancellation support, and Dispatchers.Default is provided for background coroutines.
What is the difference between threads and coroutines in Kotlin?
The README does not draw that comparison. It does document that blocking work on the JVM goes through Dispatchers.IO, that custom thread pools are available via the Executor.asCoroutineDispatcher extension, and that Dispatchers.Default handles background coroutines.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kotlin-kotlinx-coroutines)