Open-source project
kosi-libs/Kodein avatar
kosi-libs/Kodein

Kodein: Kotlin Multiplatform Dependency Injection Without the Ceremony

Painless Kotlin Dependency Injection

3,333 stars177 forksKotlinMIT

At a glance

What is it?
Kodein is a DI container for Kotlin that works across JVM, Android, Native and JS targets. It trades compile-time code generation for a declarative DSL, and that trade-off decides who should adopt it.
Who is it for?
Adopt Kodein if you are writing Kotlin Multiplatform code and want a DI container that does not depend on annotation processing or a code generator, and if you are willing to accept runtime binding resolution. Do not adopt it if you need compile-time verification of the whole graph, or if your team already has a working Koin setup and no multiplatform pain.
Can I use it commercially?
Yes. MIT 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 last received commits 72 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Kodein solves, and for whom

Kodein is a dependency retrieval container for Kotlin. The README describes it as a way to lazily instantiate dependencies when needed, stop caring about dependency initialization order, and bind classes or interfaces to an instance or a provider. That last point is the practical one: in a plain Kotlin codebase, wiring a data source into a controller usually means passing it through constructors or holding a mutable global. Kodein replaces both with a container you declare once and read from anywhere.

The audience is Kotlin developers who work across more than one target. The README lists JVM and Android, all Native platforms including iOS, macOS, Linux, Windows and WebAssembly, plus JavaScript and WasmJs. A team that shares business logic between an Android app and an iOS app needs a DI approach that compiles for both. Annotation processors and code generators are the usual answer on Android, and they are harder to carry into Kotlin/Native. Kodein's pitch is that the same declaration works everywhere.

It is not aimed at Java-first codebases. The README notes that Kodein is not subject to type erasure as Java is, which is a Kotlin reified-generics property, not something you get from a Java call site. If your project is mostly Java with a little Kotlin, this library's main advantage does not apply to you.

How the DI container actually resolves bindings

The mechanism is a container built by a DSL block, then read through delegated properties. The README's example is short enough to quote: a DI block declares bindProvider<Dice> and bindSingleton<DataSource>, and a class then declares private val ds: DataSource by di.instance(). The by di.instance() delegate is what performs the lookup. Nothing is resolved until that property is first read, which is where the lazy instantiation comes from.

bindProvider and bindSingleton differ in scope. A provider binding constructs a new value on each retrieval. A singleton binding constructs once and returns the same value afterward. Because the container holds the bindings rather than the constructed objects, initialization order stops mattering: a binding can reference another binding that has not been resolved yet, and resolution happens on demand.

The README also claims the library is fast and optimized, making extensive use of inline. That is a design statement about how the retrieval path is compiled, not a measured result, and the README publishes no benchmark. The debugging claim is more concrete: the README lists the ability to debug dependency bindings and recursions as a feature, which matters because a runtime container can produce a resolution error that a compile-time generator would have caught earlier. Treat the debug output as the substitute for compiler errors.

Installing Kodein from Maven Central

Kodein is published to Maven Central under the org.kodein.di group. The README gives the repository declaration first. In a Gradle Kotlin DSL build, that is:

kotlin
repositories {
    mavenCentral()
}

For a Kotlin Multiplatform project, the README shows the dependency added to the commonMain source set inside the kotlin block. The version placeholder in the README is written as {version}, so you replace it with the release you want, for example 7.33.0:

kotlin
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("org.kodein.di:kodein-di:7.33.0")
            }
        }
    }
}

After a Gradle sync, the container is available in common code. A first real use follows the README example directly. Declare a container, bind an interface to a provider and a concrete type to a singleton, then read the singleton through a delegate:

kotlin
val di = DI {
    bindProvider<Dice> { RandomDice(0, 5) }
    bindSingleton<DataSource> { SqliteDS.open("path/to/file") }
}

class Controller(private di: DI) {
    private val ds: DataSource by di.instance()
}

What you should see is that ds is only constructed when Controller first reads it, and that every Controller sharing the same DI instance receives the same DataSource. Note that the README uses the DI type name in the example while the surrounding prose calls the library KODEIN; the type and the project name are spelled differently, and the code is the source of truth for the type.

Version compatibility is the real installation constraint

The README carries a compatibility table, and it is the part most likely to break a build. Kodein 7.27 requires Kotlin 2.2.+ and a minimum JDK of 17. Kodein 7.26 requires Kotlin 2.1.+ and JDK 17. Kodein 7.23 requires Kotlin 2.0.+ and JDK 17. Kodein 7.22 requires Kotlin 2.0.+ but drops the floor to JDK 11. Kodein 7.21 requires Kotlin 1.9.+ and JDK 1.8. Older lines, 7.20 down to 7.17, are pinned to Kotlin 1.8.x and JDK 1.8.

The pattern is that the JDK floor moved from 8 to 11 to 17 across the 7.21 to 7.23 range, while the Kotlin floor moved independently. If you are on an older Android Gradle Plugin that cannot compile against JDK 17, you cannot simply take the newest Kodein. The README points to a fuller table at kosi-libs.org under core/platform-and-genericity.html, which is where the rows beyond 7.27 live. The README's own table stops at 7.27 even though 7.33.0 is the newest release listed, so the compatibility data for the current releases is not in the README.

There is a second cost signal in the repository layout. There are separate top-level directories for kodein-di, kodein-di-conf, kodein-di-jxinject-jvm, framework, and compiler. The compiler directory suggests a Gradle plugin or compiler component exists alongside the runtime library, but the README does not describe it, so do not assume it is required for basic use.

Where Kodein is the wrong tool

The central limitation is that bindings are resolved at runtime. A missing binding, a circular dependency, or a type mismatch surfaces when the delegate is first read, not when the project compiles. The README lists debugging bindings and recursions as a feature, which is an implicit acknowledgement that these failures happen. For a large application with hundreds of bindings and no test that touches every entry point, that means a class of errors can reach a running app.

Compile-time DI frameworks take the opposite position: they generate the wiring and fail the build when the graph is incomplete. If your team's requirement is that an unsatisfied dependency cannot ship, Kodein does not give you that guarantee, and the README does not claim it does.

A second boundary is the integration surface. The README lists extensions for Android, Compose on Android, Desktop and Web, and Ktor. Those integrations live under the framework directory and are documented at kosi-libs.org rather than in the README. If your target is a server framework other than Ktor, or a UI toolkit other than Compose or TornadoFX, the README gives you the core container and nothing tailored to your stack. That is workable, because the core container is target-agnostic, but you will be writing the glue yourself.

Finally, the README is thin on error handling. It does not document what happens when a binding is requested but not declared, nor does it describe rollback or recovery behavior. If you need to know the exact exception type and message before adopting, the README will not tell you.

Koin vs Kodein: the difference in approach

Koin is the comparison most Kotlin developers reach for, and the two libraries solve the same problem from different starting points. Koin's model is a module DSL evaluated at runtime with a global registry that you start and stop. Kodein's model is a container object you construct and pass around explicitly, as the README example shows with class Controller(private di: DI).

The practical consequence is ownership. With an explicit DI instance, a test can build a container with test-specific bindings and hand it to the class under test without touching any global state. With a global registry, test isolation depends on setup and teardown discipline. Neither approach is wrong, but if you have been bitten by test order dependence, the explicit container is the easier story to tell.

The second difference is the multiplatform story. Kodein's README makes multiplatform support the headline, listing JVM, Android, all Native platforms, JS and WasmJs, and the repository layout reflects that with a common kodein-di module. If you are targeting Kotlin/Native or WasmJs, that is the axis worth comparing on, and it is the axis where the README is most specific about Kodein's intent.

A third option worth naming is manual constructor injection with no container at all. For a small app, passing dependencies through constructors costs nothing and removes a dependency. Kodein earns its place when the graph is deep enough that manual wiring becomes noise, or when you need the same graph on multiple platforms.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-07-21, which is the same date as the 7.33.0 release. The two releases before it were 7.32.0 on 2026-04-29 and 7.31.0 on 2026-02-08. That is a release roughly every two to three months across the visible window, which tells you the project is being published to, and the CHANGELOG.md at the repository root is where the per-release detail lives. The README itself does not describe a support policy or a deprecation timeline, so version upgrades are your responsibility to read up on.

The licence is MIT, declared in the README badge and in LICENSE.txt at the repository root. MIT is permissive: it allows commercial use and modification, and it requires that the copyright notice and licence text be preserved in distributions. That is a statement about what the licence text says, not legal advice for your situation; if your organization has a policy on third-party licences, run it through that process.

The upgrade cost is concentrated in the compatibility table. Because the Kotlin and JDK floors move across minor versions, a Kodein bump can force a Kotlin bump, which can force an Android Gradle Plugin bump. Plan the upgrade as a toolchain change, not a library change. The README also notes that documentation is available for previous versions at kosi-libs.org, which helps when you are pinned to an older line but does not remove the toolchain coupling.

Support runs through the Kodein Slack channel, linked from the README, with invitations available from the Kotlin Slack. There is no issue-tracker support statement in the README.

Editorial conclusion

Adopt Kodein if you are writing Kotlin Multiplatform code and want a DI container that does not depend on annotation processing or a code generator, and if you are willing to accept runtime binding resolution. Do not adopt it if you need compile-time verification of the whole graph, or if your team already has a working Koin setup and no multiplatform pain. Before committing, check the Kotlin and JDK row that matches the Kodein version you plan to use, and open the Compose or Ktor extension docs for your target, because the core README does not cover those integrations in detail.

Frequently asked questions

How does Kodein compare with Koin?

Both are runtime DI containers for Kotlin. Kodein's README example builds an explicit DI container that is passed into a class and read through a by di.instance() delegate, whereas Koin's model is a module DSL with a global registry. Kodein's README makes Kotlin Multiplatform support its headline feature.

How do I install Kodein in a Kotlin Multiplatform project?

Add mavenCentral() to your repositories and then add implementation("org.kodein.di:kodein-di:{version}") to the commonMain source set inside the kotlin block, replacing {version} with the release you want. The README shows exactly this layout.

Which Kotlin and JDK versions does Kodein require?

The README's compatibility table shows Kodein 7.27 requires Kotlin 2.2.+ and JDK 17, 7.26 requires Kotlin 2.1.+ and JDK 17, 7.23 requires Kotlin 2.0.+ and JDK 17, 7.22 requires Kotlin 2.0.+ and JDK 11, and 7.21 requires Kotlin 1.9.+ and JDK 1.8. The README points to kosi-libs.org for the full table.

Does Kodein work with Jetpack Compose and Ktor?

Yes. The README lists extensions for Android, Compose on Android, Desktop and Web, and Ktor. Those integrations are documented on kosi-libs.org rather than in the README itself.

What licence does Kodein use?

MIT, shown as a badge in the README and included as LICENSE.txt at the repository root. That permits commercial use and modification provided the copyright notice and licence text are preserved.

Official sources

  1. kosi-libs/Kodein on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kosi-libs-kodein.svg)](https://hysenlabs.com/projects/kosi-libs-kodein)