docs/intro/what-is-koin.md
Koin is a lightweight dependency injection framework designed specifically for Kotlin. Unlike traditional DI frameworks that rely on code generation or reflection, Koin offers two equally powerful approaches: a clean Kotlin DSL and intuitive Annotations. Choose what fits your team - both are first-class citizens.
| Value | What it means |
|---|---|
| Productive | Easy to learn, easy to write. Get DI working in minutes, not hours |
| Developer-Friendly | DSL or Annotations - your choice. Clear errors, easy debugging, best DX |
| Scalable | Powers large enterprise applications with complex dependency graphs |
| Safe | Compile-time safety with Koin Compiler Plugin |
| Dynamic | Runtime flexibility: load modules dynamically, lazy loading, feature flags |
Koin supports two styles of defining dependencies. Both are first-class citizens with full feature parity. Choose what fits your team:
Define dependencies using Kotlin DSL syntax:
val appModule = module {
single<Database>()
single<ApiClient>()
single<UserRepository>()
viewModel<UserViewModel>()
}
Define dependencies using annotations:
@Singleton
class Database
@Singleton
class ApiClient
@Singleton
class UserRepository(
private val database: Database,
private val apiClient: ApiClient
)
@KoinViewModel
class UserViewModel(private val repository: UserRepository) : ViewModel()
Both styles are processed by the Koin Compiler Plugin for compile-time safety.
If you've used Hilt or Dagger, you'll notice Koin annotations require less ceremony:
| Task | Koin | Hilt |
|---|---|---|
| Singleton | @Singleton class MyService | @Singleton class MyService @Inject constructor(...) |
| Interface binding | Automatic (just implement the interface) | Requires @Binds in abstract module |
| Component scanning | @ComponentScan("package") | Not available |
| Module discovery | @Configuration - auto-discovered | Manual @InstallIn per module |
Example comparison:
// KOIN - That's it!
@Singleton
class MyRepository(val api: ApiService)
@Module
@ComponentScan("com.app")
class AppModule
// HILT - More ceremony
@Singleton
class MyRepository @Inject constructor(val api: ApiService)
@Module
@InstallIn(SingletonComponent::class)
abstract class AppModule {
@Binds
abstract fun bindRepository(impl: MyRepository): Repository
}
The Koin Compiler Plugin is the recommended way to use Koin for all new projects:
| Classic DSL | Compiler Plugin DSL |
|---|---|
singleOf(::MyService) | single<MyService>() |
single { MyService(get(), get()) } | single<MyService>() |
factoryOf(::MyRepo) | factory<MyRepo>() |
viewModelOf(::MyVM) | viewModel<MyVM>() |
Learn more in Koin Compiler Plugin.
The classic DSL remains fully supported for all Kotlin versions:
val appModule = module {
singleOf(::Database)
singleOf(::ApiClient)
singleOf(::UserRepository)
viewModelOf(::UserViewModel)
}
Or with explicit wiring:
val appModule = module {
single { Database() }
single { ApiClient() }
single { UserRepository(get(), get()) }
viewModel { UserViewModel(get()) }
}
:::info Classic DSL is not deprecated. Koin works perfectly with it. The Compiler Plugin adds compile-time analysis on top when you're ready to migrate. :::
The koin-annotations library — @Singleton, @Factory, @KoinViewModel, @Module, @ComponentScan, and the rest — ships under the main Koin version and is fully supported. It is not deprecated.
dependencies {
implementation(platform("io.insert-koin:koin-bom:$koin_version"))
implementation("io.insert-koin:koin-core")
implementation("io.insert-koin:koin-annotations") // same Koin version
}
Your annotations are processed by the Koin Compiler Plugin — see Koin Compiler Plugin and the Annotations Reference.
:::info
The legacy KSP processor koin-ksp-compiler is deprecated and will be removed in a future Koin version. The replacement is the Koin Compiler Plugin — native K2 compiler integration, no generated files, simpler KMP setup.
:::
If you're using Koin Annotations with koin-ksp-compiler, migrate to the Compiler Plugin:
See Migrating from KSP to Compiler Plugin.
Koin is runtime-based but performant and compile-safe. This unique combination enables:
Compile-time safety (with Compiler Plugin):
Runtime flexibility (that compile-time-only frameworks can't offer):
// Dynamic module loading - impossible with Hilt
if (featureEnabled) {
loadKoinModules(premiumFeatureModule)
}
// Later, if feature disabled
unloadKoinModules(premiumFeatureModule)
Koin is ideal for: