What is Koin?
Koin is a dependency injection framework for Kotlin. This page explains how it works, what it costs and what it gives you, and how the project is organized. If dependency injection is new to you, read What is Dependency Injection? first.
How Koin works
You describe your classes in modules, start Koin once, and ask for instances where you need them:
class ApiService
class UserRepository(private val api: ApiService)
val appModule = module {
single<ApiService>()
single<UserRepository>()
}
fun main() {
startKoin {
modules(appModule)
}
}
Two parts work together:
- Runtime container:
startKoinloads your modules into a container. Each definition is a Kotlin function that builds one type. When something asks for aUserRepository, Koin runs that function, resolves its constructor parameters from the container, and keeps or discards the instance depending on the definition type (single,factory,scoped). Koin does not build objects by reflection. - Compile-time checks (optional): the Koin Compiler Plugin is a Kotlin compiler plugin. It reads your constructors to generate the wiring, then checks at build time that every dependency of the assembled graph is declared. A missing definition becomes a build error instead of a crash.
Core Concepts explains modules, definitions, scopes and injection with one running example.
What the runtime model costs and gives
Because the graph lives in a runtime container, Koin can change it while the app runs:
- Dynamic modules: load and unload modules after start with
loadKoinModules()andunloadKoinModules(), for feature flags or on-demand features. See Starting Koin. - Lazy modules: load part of the graph in the background to reduce startup work. See Lazy Modules.
- Scopes created at runtime: open and close scopes for a session, a screen or a request. See Scopes.
- No generated sources: nothing to commit, nothing to configure per Kotlin Multiplatform target.
The same model has costs you should know:
- Startup work: modules are registered when Koin starts, and every lookup goes through the container. For most apps this is small, but eager definitions (
createdAtStart) run on the thread that starts Koin. - Runtime errors without the plugin: with the Constructor or Classic DSL and no plugin, a missing definition is only found when the code runs. You can catch it in a unit test with
verify(), or at build time with the Compiler Plugin. - Limits of compile-time checks: the plugin validates the graph assembled at a Koin entry point such as
startKoin. Modules loaded later withloadKoinModules()can't be proven at build time, and a library module with no entry point is only checked when an app assembles it. See Compile-Time Safety. - Kotlin version coupling: the Compiler Plugin depends on compiler internals, so each plugin release is verified on a list of Kotlin versions. See Compiler Plugin Setup.
Constructor injection and service locator
Your classes receive their dependencies through the constructor. Koin only retrieves an instance where it cannot create the object itself, at an entry point:
// Koin creates these: dependencies come through the constructor
class UserRepository(private val api: UserApi)
class UserViewModel(private val repository: UserRepository) : ViewModel()
// Android creates the Activity: it retrieves its ViewModel from Koin
class UserActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModel()
}
The dependency is visible in the signature, and you can test UserRepository and UserViewModel without Koin. Retrieval functions such as by inject(), by viewModel() or koinInject() belong to entry points: an Activity, a Fragment, a root Composable, main(), a Ktor route, a test. What is Dependency Injection? compares the two patterns, and Retrieving Dependencies covers get() and inject().
Two styles, one container
| Style | Example | Needs |
|---|---|---|
| Compiler Plugin DSL | single<UserRepository>() | Koin Compiler Plugin |
| Annotations | @Singleton class UserRepository(...) | Koin Compiler Plugin, koin-annotations |
| Constructor DSL | singleOf(::UserRepository) | Nothing extra (the plugin adds compile-time checks) |
| Classic DSL | single { UserRepository(get()) } | Nothing extra (the plugin adds compile-time checks) |
Annotations are one style; the Compiler Plugin, Constructor and Classic DSL are the three forms of the other, the Koin DSL. All produce the same definitions in the same container. Pick one style per project. Choosing your style compares them and gives a default.
Annotations status
The koin-annotations library (@Singleton, @Factory, @KoinViewModel, @Module, @ComponentScan) is part of the main Koin project: same repository, same version, same BOM. It is not deprecated. What is deprecated is koin-ksp-compiler, the KSP processor that used to read these annotations. The Koin Compiler Plugin replaces it, with the same annotations. See Migrating from KSP to the Compiler Plugin.
Platforms
Koin is a Kotlin Multiplatform library. The core runs on every Kotlin target, and integration libraries add platform APIs:
| Platform | Main artifact | Start here |
|---|---|---|
| Kotlin/JVM | koin-core | Kotlin tutorial |
| Android | koin-android | Start Koin on Android |
| Jetpack Compose, Compose Multiplatform | koin-compose, koin-compose-viewmodel | Koin for Compose |
| Kotlin Multiplatform (iOS, desktop, web, native) | koin-core | Kotlin Multiplatform Setup |
| Ktor server | koin-ktor | Koin for Ktor |
The full artifact list is in Gradle Setup.
The Koin project
Koin is open source under the Apache 2.0 license. It is made of:
- Koin libraries: core, Android, Compose, Ktor, test and annotations, all released under one version. Source: InsertKoinIO/koin.
- Koin Compiler Plugin: the Kotlin compiler plugin and its Gradle plugin, with its own version. Source: InsertKoinIO/koin-compiler-plugin.
- Koin IDE Plugin: navigation and checks in Android Studio and IntelliJ IDEA. See IDE Plugin.
- Samples: runnable apps for each tutorial in InsertKoinIO/koin-getting-started.
If you know Hilt or Dagger, Koin vs Hilt compares the two approaches.
Related
- Core Concepts: the mental model, with one example built step by step.
- Choosing your style: which declaration style to use.
- Koin Compiler Plugin: what happens at build time.
- Setup: add Koin to your project.
- Tutorials: build a first app.