docs/reference/koin-ktor/ktor-bridge.md
Koin 4.2+ provides seamless integration with Ktor 3.4+ built-in dependency injection system through a configurable bridge.
:::info Experimental Feature The Ktor DI Bridge is an experimental feature that enables bidirectional dependency resolution between Koin and Ktor DI. :::
Use the bridge { } DSL to enable bidirectional dependency resolution:
fun Application.module() {
install(Koin) {
slf4jLogger()
bridge {
ktorToKoin() // Ktor DI can resolve Koin dependencies
koinToKtor() // Koin can resolve Ktor DI dependencies
}
modules(appModule)
}
// Ktor DI dependencies
dependencies {
provide<KtorSpecificService> { KtorSpecificServiceImpl() }
}
}
| Option | Description |
|---|---|
ktorToKoin() | Allows Ktor's by dependencies delegate to resolve from Koin |
koinToKtor() | Allows Koin's inject() and get() to resolve from Ktor DI |
Resolve Koin dependencies using Ktor's by dependencies delegate:
fun Application.module() {
install(Koin) {
bridge {
ktorToKoin()
}
modules(module {
single<HelloService> { HelloServiceImpl() }
})
}
routing {
get("/hello") {
// Resolve Koin dependency using Ktor's delegate
val helloService: HelloService by dependencies
call.respondText(helloService.sayHello())
}
}
}
Resolve Ktor DI dependencies using Koin's inject():
fun Application.module() {
install(Koin) {
bridge {
koinToKtor()
}
modules(appModule)
}
// Declare in Ktor DI
dependencies {
provide<DatabaseConnection> { DatabaseConnectionImpl() }
}
routing {
get("/data") {
// Resolve Ktor DI dependency using Koin
val database: DatabaseConnection by inject()
call.respondText(database.query())
}
}
}
Enable both directions for maximum flexibility:
fun Application.module() {
install(Koin) {
slf4jLogger()
bridge {
ktorToKoin()
koinToKtor()
}
modules(module {
single<HelloService> { HelloServiceImpl() }
})
}
dependencies {
provide<KtorSpecificService> { KtorSpecificServiceImpl() }
}
routing {
// Using Koin's inject() for both
get("/mixed-koin") {
val helloService: HelloService by inject() // From Koin
val ktorService: KtorSpecificService by inject() // From Ktor DI
call.respondText("${helloService.sayHello()} - ${ktorService.process()}")
}
// Using Ktor's dependencies delegate for both
get("/mixed-ktor") {
val helloService: HelloService by dependencies // From Koin
val ktorService: KtorSpecificService by dependencies // From Ktor DI
call.respondText("${helloService.sayHello()} - ${ktorService.process()}")
}
}
}
Separate infrastructure from application logic:
fun Application.module() {
// Ktor DI - Infrastructure layer
val config = environment.config
val database = Database(config)
dependencies {
provide<Database> { database }
provide<ApplicationConfig> { config }
}
// Koin - Application layer
install(Koin) {
slf4jLogger()
bridge {
koinToKtor() // Koin can resolve infrastructure deps
}
modules(appModule)
}
}
val appModule = module {
// These can inject Database from Ktor DI via bridge
singleOf(::CustomerRepository)
singleOf(::OrderRepository)
singleOf(::CustomerService)
}
koinToKtor() only, not both, unless necessaryThe bridge also works with KoinIsolated:
fun Application.module() {
dependencies {
provide<Database> { Database(environment.config) }
}
install(KoinIsolated) {
slf4jLogger()
bridge {
koinToKtor()
}
modules(appModule)
}
}