{"id":644121,"date":"2025-09-23T20:00:47","date_gmt":"2025-09-23T19:00:47","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=644121"},"modified":"2025-10-06T13:48:10","modified_gmt":"2025-10-06T12:48:10","slug":"ktor-roadmap-2025","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/ja\/kotlin\/2025\/09\/ktor-roadmap-2025","title":{"rendered":"Ktor Roadmap and Previews"},"content":{"rendered":"\n<p>Like in previous years, we have been working on the Ktor roadmap, and we want to thank everyone for their contributions and feedback to help us prioritize our areas of development for Ktor!<\/p>\n\n\n\n<p>The OpenAPI and WebRTC support is already in preview since Ktor 3.3.0. Check out the <a href=\"https:\/\/ktor.io\/docs\/whats-new-330.html\" data-type=\"link\" data-id=\"https:\/\/ktor.io\/docs\/whats-new-330.html\" target=\"_blank\" rel=\"noopener\">What\u2019s New<\/a> section for a full overview of Ktor 3.3.0.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">? Get started with ktor<\/h2>\n\n\n\n<p>Ready to explore Ktor? Start building your next project today with our interactive project generator at <a href=\"https:\/\/kotl.in\/ixiien\" target=\"_blank\" rel=\"noopener\">start.ktor.io<\/a>. Your feedback and contributions are always welcome!<br><br>?<a href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\"> Get Started With Ktor<\/a> | ? Join the Community on<a href=\"https:\/\/www.reddit.com\/r\/ktor\/\" target=\"_blank\" rel=\"noopener\"> Reddit<\/a> and<a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up?_gl=1*1wxglsg*_gcl_au*MTE4MjgxMTg3Mi4xNzM2MjY0ODgy*_ga*MTYyODczMDg5NS4xNzAyMDQyMTMx*_ga_9J976DJZ68*MTczODY3Mjg3Ny4xOTguMS4xNzM4NjczNDI2LjM2LjAuMA..\" target=\"_blank\" rel=\"noopener\"> Slack<\/a><\/p>\n\n\n\n<div class=\"buttons\">\n        <div class=\"buttons__row\">\n            <a class=\"ek-link jb-download-button\" title=\"Get Started With Ktor\" href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\" data-test=\"blog-article-cta\" data-cl=\"true\">Get Started With Ktor<\/a>\n         <\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Ktor library improvement process<\/h2>\n\n\n\n<p>The Ktor team is always looking for feedback, and therefore we fully develop everything in the open, including creating feature proposals similar to KEEPs but for Ktor. This is called KLIP, or Ktor library improvement process, and it can be found on <a href=\"https:\/\/github.com\/ktorio\/ktor-klip\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>. So keep an eye out for future proposals in case you\u2019ve missed it, and please provide any feedback you might have.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">(Open)API documentation<\/h2>\n\n\n\n<p>API documentation, currently one of the most requested features, has gone into development. ? In Ktor 3.3.0, it was included in an early preview so you can provide early feedback. Check out the<a href=\"https:\/\/github.com\/ktorio\/ktor-klip\/pull\/3\" target=\"_blank\" rel=\"noopener\"> OpenAPI KLIP<\/a> or the <a href=\"https:\/\/github.com\/bjhham\/open-api-eap-template\" target=\"_blank\" rel=\"noopener\">Ktor OpenAPI Template project<\/a>.<\/p>\n\n\n\n<p>Ktor can automatically provide an OpenAPI model from analyzing your code at compile-time, and can be set up in a simple way from Gradle. The <a href=\"https:\/\/github.com\/ktorio\/ktor-build-plugins\" target=\"_blank\" rel=\"noopener\">Ktor Gradle Plugin<\/a> has a new openapi configuration which can be used to provide OpenAPI information and set up project-related configurations. The plugin currently only supports Kotlin 2.2.20. Additionally, you&#8217;ll need to add a Maven dependency for the <code>ktor-server-openapi<\/code> module, or <code>ktor-server-swagger<\/code> depending on your preference.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">plugins {\n    kotlin(libs.plugins.kotlin)\n    alias(libs.plugins.ktor)\n}\n\nktor {\n    @OptIn(OpenApiPreview::class)\n    openapi {\n        target = project.layout.projectDirectory.file(\"api.json\")\n        \n        title = \"My Service\"\n        summary = \"What it does\"\n        description = \"A longer description of the service\"\n        version = \"1.0.0\"        \n        \/\/ contact, termsOfService, license...\n    }\n}\n\ndependencies {\n    implementation(libs.ktor.server.core)\n    implementation(libs.ktor.server.openapi)\n}<\/pre>\n\n\n\n<p>}<\/p>\n\n\n\n<p>To find out more about the api documentation support, check out <a href=\"https:\/\/github.com\/ktorio\/ktor-klip\/pull\/3\" target=\"_blank\" rel=\"noopener\">the proposal<\/a> or try it yourself in your project using <a href=\"https:\/\/github.com\/bjhham\/open-api-eap-template\" target=\"_blank\" rel=\"noopener\">the template project<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Service discovery<\/h2>\n\n\n\n<p>In distributed systems, service discovery is a critical part of the distributed system. As servers become available, clients need to be able to discover them. The Service Discovery plugin eliminates the need to manually <em>register<\/em> the services, and <em>resolve<\/em> the client. The plugin offers a unified abstraction layer over popular discovery mechanisms (<a href=\"https:\/\/developer.hashicorp.com\/consul\" target=\"_blank\" rel=\"noopener\">Consul<\/a>, <a href=\"https:\/\/kubernetes.io\/\" target=\"_blank\" rel=\"noopener\">Kubernetes<\/a>, <a href=\"https:\/\/zookeeper.apache.org\/\" target=\"_blank\" rel=\"noopener\">Zookeeper<\/a>, <a href=\"https:\/\/github.com\/Netflix\/eureka\/wiki\" target=\"_blank\" rel=\"noopener\">Eureka<\/a>) while offering both client-side and server-side discovery patterns. This allows you to configure service discovery in a way that&#8217;s idiomatic for Ktor and Kotlin.<\/p>\n\n\n\n<p>In the example below, we configure the <code>ServiceDiscovery<\/code> plugin to automatically register our <code>sample-service<\/code> on port <code>8080<\/code> with the consul service registry on <code>localhost:8500<\/code>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">install(ServiceDiscovery) {\n   consul {\n      connection {\n         host = \"localhost\"\n         port = 8500\n      }\n\n      registration {\n         serviceName = \"sample-service\"\n         instanceId = \"sample-service:$host:$port\"\n         port = 8080\n      }\n   }\n}<\/pre>\n\n\n\n<p>Another service needs to be able to communicate with the <code>sample-service<\/code>. In a distributed system, it doesn\u2019t matter which instance we use, so we rely on the service registry to resolve the <code>serviceName<\/code> into a registered <code>instanceId<\/code>. The <code>HttpClient<\/code> <code>ServiceDiscovery<\/code> plugin allows us to conveniently do so.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val client = HttpClient {\n    install(ServiceDiscovery) {\n       consul {\n          connection {\n             host = \"localhost\"\n             port = 8500\n          }\n       }\n    }\n}\nclient.get(\"service:\/\/sample-service\")<\/pre>\n\n\n\n<p>The <code>HttpClient<\/code> is configured with the <code>ServiceDiscovery<\/code> plugin connected to the same Consul service registry as our server example. Once configured, we can use <code>service:\/\/name<\/code> to resolve a service within our distributed system, which in this case is the <code>sample-service<\/code>.<\/p>\n\n\n\n<p><br>To find out more about the service discovery support, check out <a href=\"https:\/\/github.com\/ktorio\/ktor-klip\/pull\/2\" target=\"_blank\" rel=\"noopener\">the proposal<\/a>, and please share your feedback.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WebRTC<\/h2>\n\n\n\n<p>Real-time peer-to-peer communication is becoming increasingly useful for various applications, ranging from video calls to multiplayer and collaborative tools. We&#8217;re working on bringing WebRTC Client support to Ktor with a unified, multiplatform API that works seamlessly across browsers, Android, and potentially other platforms.<\/p>\n\n\n\n<p>Signaling (WebSocket, HTTP, etc.) still manually needs to be managed but we&#8217;re focusing on making the peer-to-peer connection part as smooth as possible. Ktor 3.3.0 supports JS\/Wasm and Android platforms, with more platforms like JVM, iOS, Native coming. Support for an experimental Rust-based WebRTC client is also planned. This could pave the way for integrating Rust components in other areas of Ktor. More details can be found in the <a href=\"https:\/\/github.com\/ktorio\/ktor-klip\/pull\/4\" target=\"_blank\" rel=\"noopener\">KLIP<\/a>, or the full stack KMP <a href=\"https:\/\/github.com\/ktorio\/ktor-chat\/\" target=\"_blank\" rel=\"noopener\">Ktor Video Chat<\/a> example.<\/p>\n\n\n\n<p>A <code>WebRtcClient<\/code> is created by providing the engine instance and configuring the platform-specific configuration similar to <code>HttpClient<\/code>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val jsClient = WebRtcClient(JsWebRtc) {\n defaultConnectionConfig = {\n   iceServers = listOf(WebRtc.IceServer(\"stun:stun.l.google.com:19302\"))\n }\n}\nval androidClient = WebRtcClient(AndroidWebRtc) {\n context = appContext \/\/ provide Android context\n defaultConnectionConfig = { \/* Same default config*\/ }\n}<\/pre>\n\n\n\n<p>WebRTC clients need to create an RTC peer-to-peer connection which they establish using the Interactive Connectivity Establishment (ICE). After the peers have connected, they can send and receive data from each other using the channels.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val jsConnection = jsClient.createPeerConnection()\njsConnection.addIceCandidate(WebRtc.IceCandidate(candidateString, sdpMid, sdpMLineIndex))\njsConnection.awaitIceGatheringComplete()\n\n\njsConnection.dataChannelEvents.collect { event ->\n   when (event) {\n     is Open -> println(\"Another peer opened a chanel: ${event.channel}\")\n     is Closed -> println(\"Data channel is closed\")\n     is Closing, is BufferedAmountLow, is Error -> println(event)\n   }\n}\n<\/pre>\n\n\n\n<p><br>To find out more about the WebRTC support check out <a href=\"https:\/\/github.com\/ktorio\/ktor-klip\/pull\/4\" target=\"_blank\" rel=\"noopener\">the proposal<\/a>, and please share any feedback you may have.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">gRPC: powered by kotlinx-rpc<\/h2>\n\n\n\n<p>gRPC support in Ktor is finally here! But with a catch. The kotlinx-rpc library is doing all the heavy lifting of bringing gRPC support to Ktor. kotlinx-rpc is dedicated to bringing you the best gRPC experience in Kotlin. Let&#8217;s define a new <code>GrpcService<\/code> in a <em>common module<\/em> and then use it on both the server side and client side.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Grpc\ninterface GrpcService {\n    suspend fun sayHello(request: HelloRequest): HelloResponse\n}<\/pre>\n\n\n\n<p>Our server-side implementation might look like this, and we can register it in our Ktor <code>Application<\/code> using the <code>grpc<\/code> DSL.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">interface GrpcServiceImpl : MyService {\n    suspend fun sayHello(request: HelloRequest): HelloResponse {\n        return HelloResponse { content = \"Hello, ${request.name}\" }\n    }\n}\n\nfun Application.installGrpc() = grpc {\n    registerService&lt;MyService> { MyServiceImpl() }\n}<\/pre>\n\n\n\n<p>Depending on your use cases or existing systems, you might prefer working with <code>.proto<\/code> files instead. The <code>interface GrpcService<\/code> can also be defined from <code>.proto<\/code>, and it\u2019ll generate the same interface as above, allowing the same implementation and Ktor usage.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax = \"proto3\";\n\npackage io.ktor;\n\nservice MyService {\n  rpc sayHello(HelloRequest) returns (HelloResponse);\n}<\/pre>\n\n\n\n<p>You can also use generated messages from <code>.proto<\/code> files.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">message HelloRequest {\n  string name = 1;\n}\n\nmessage HelloResponse {\n  string content = 1;\n}<\/pre>\n\n\n\n<p>Alternatively, you can also use KotlinX\u2019s <code>@Seriazable<\/code> or your preferred serialization techniques.<br><br>Support for Apple and Linux, beyond the JVM, is planned. Check out our <a href=\"https:\/\/github.com\/Kotlin\/kotlinx-rpc\" target=\"_blank\" rel=\"noopener\">kotlinx-rpc<\/a> for more details.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Koog integration<\/h2>\n\n\n\n<p>The new Ktor Koog Plugin makes it easy for you to create agentic services with Ktor and Koog. It aims to provide a deep integration between Koog and Kotlin\u2019s AI ecosystem.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">fun Application.module() {\n    install(Koog)\n    \n    routing {\n        get(\"\/execute\/{prompt}\") {\n            val prompt = call.parameters.getOrFail(\"prompt\")\n            val output = aiAgent(customStrategy(), GPT4_1, prompt)\n            call.respond(HttpStatusCode.OK, output)\n        }\n    }\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Dependency injection<\/h2>\n\n\n\n<p>Dependency injection support was released earlier this year, as discussed in last year&#8217;s roadmap post. In the OpenAPI Documentation feature, we\u2019re introducing a compiler plugin to Ktor to generate documentation at compile time. This is the perfect opportunity to further enhance our dependency injection support with compile-time verification and provide better support for other platforms.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">fun Application.dependencies() = dependencies {\n   provide&lt;HikariDataSource> { hikariSource() }\n   provide&lt;R2dbcDatabase> { exposed(get()) } \n   provide&lt;MyService>(::MyServiceImpl)\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>? <\/strong>&nbsp;Get started with Ktor 3.3.0<\/h2>\n\n\n\n<p>Ready to explore Ktor 3.3.0? Start building your next project today with our interactive project generator at <a href=\"https:\/\/kotl.in\/ixiien\" target=\"_blank\" rel=\"noopener\">start.ktor.io<\/a>. Your feedback and contributions are always welcome!<\/p>\n\n\n\n<p>We want to thank<a href=\"https:\/\/github.com\/MarcusDunn\" target=\"_blank\" rel=\"noopener\"> <\/a>everyone in the community for your support and feedback, as well as for reporting issues.<\/p>\n\n\n\n<p>?<a href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\"> Get Started With Ktor<\/a> | ? Join the Community on <a href=\"https:\/\/www.reddit.com\/r\/ktor\/\" target=\"_blank\" rel=\"noopener\">Reddit<\/a> and<a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up?_gl=1*1wxglsg*_gcl_au*MTE4MjgxMTg3Mi4xNzM2MjY0ODgy*_ga*MTYyODczMDg5NS4xNzAyMDQyMTMx*_ga_9J976DJZ68*MTczODY3Mjg3Ny4xOTguMS4xNzM4NjczNDI2LjM2LjAuMA..\" target=\"_blank\" rel=\"noopener\"> Slack<\/a><\/p>\n","protected":false},"author":1566,"featured_media":644153,"comment_status":"closed","ping_status":"closed","template":"","categories":[4897,89,907],"tags":[4292,76,477],"cross-post-tag":[6634],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/644121"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/users\/1566"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/comments?post=644121"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/644121\/revisions"}],"predecessor-version":[{"id":646818,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/644121\/revisions\/646818"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media\/644153"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media?parent=644121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/categories?post=644121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/tags?post=644121"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/cross-post-tag?post=644121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}