Library / SDK
Kotlin/kotlinx-rpc avatar
Kotlin/kotlinx-rpc

kotlinx.rpc: RPC services as ordinary Kotlin interfaces

Add asynchronous RPC services to your multiplatform applications.

1,078 stars52 forksKotlinApache-2.0

At a glance

What is it?
kotlinx.rpc is a JetBrains project that turns a Kotlin interface into a remote service, with Flow returning functions and suspend functions handled by a compiler plugin that generates the client and server code for you. The interesting parts of the project are its shape: a transport agnostic core, a Ktor based kRPC implementation, and a gRPC module that is JVM only today.
Who is it for?
kotlinx.rpc fits a Kotlin Multiplatform team that wants one service definition to work on the JVM, on Kotlin/JS and on native targets, and that is prepared to accept an experimental library in exchange for a shared interface rather than a generated client from a schema.
Can I use it commercially?
Yes. Apache-2.0 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 7 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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An interface, an annotation, and a compiler plugin

kotlinx.rpc is a Kotlin library for adding asynchronous Remote Procedure Call services to your applications, and the summary line in the README is the whole pitch: build your RPC with already known language constructs and nothing more.

A service is an interface with an annotation.

kotlin
@Rpc
interface AwesomeService {
    fun getNews(city: String): Flow<String>
    
    suspend fun daysUntilStableRelease(): Int
}

The two function shapes matter. A plain function returning a Flow is a streaming call, where the server pushes a sequence of values, and a suspend function is a single request and response. The client sees the same signatures it would see if the implementation were in the same process, which is the point of the design.

The server implements the interface and nothing else changes about how the method bodies are written.

kotlin
class AwesomeServiceImpl(val parameters: AwesomeParameters) : AwesomeService {
    override fun getNews(city: String): Flow<String> {
        return flow { 
            emit("Today is 23 degrees!")
            emit("Harry Potter is in $city!")
            emit("New dogs cafe has opened doors to all fluffy customers!")
        }
    }

The work of turning that into a network service happens in code generation. The library ships a Gradle plugin, org.jetbrains.kotlinx.rpc.plugin, which sets up code generation in a project, and the repository has a compiler-plugin/ directory where that plugin lives.

The project is an official JetBrains project, it is licensed under Apache-2.0, and it carries the Kotlin Experimental badge, which is the single most important thing to know about it before you plan around it.

The transport is a decision you make later

The library is designed to be transport agnostic, which means it aims to provide the best RPC experience regardless of how the services are connected.

In practice, the first integration is Ktor, and both halves are shown in the quick start. On the server you install the Krpc plugin into an embedded Netty server, configure the serialization inside an rpcConfig block, and register the service implementation.

kotlin
data class AwesomeParameters(val stable: Boolean, val daysUntilStable: Int?)

fun main() {
    embeddedServer(Netty, 8080) {
        install(Krpc)
        routing {
            rpc("/awesome") {
                rpcConfig {
                    serialization {
                        json()
                    }
                }

On the client, you install the RPC support into an HTTP client, point it at a URL, configure the same serialization, and then ask for a typed view of the service.

kotlin
val rpcClient = HttpClient { installKrpc() }.rpc {
    url("ws://localhost:8080/awesome")

    rpcConfig {
        serialization {
            json()
        }
    }
}

val service = rpcClient.withService<AwesomeService>()

Two details are worth noticing. The client URL is a WebSocket address, which tells you the default kRPC transport rides on a persistent connection rather than on a request and response per call, and the serialization configuration is symmetric between the two sides, which is the kind of detail that usually has to be repeated in prose somewhere and here is just a shared function call.

The runtime dependencies are published as separate artifacts for the client API, the server API, the serialization modules and the Ktor transports, so you only take the pieces you use. JSON is the default in the example, and the README notes that protobuf and cbor are provided as well.

Three modules with three different platform stories

The support table in the README is the clearest summary of the project's state, and it is worth reading line by line because the three subsystems are not equally mature.

Core supports the JVM, JS, WasmJs, WasmWasi, and the Apple, Linux and Windows native targets. The kRPC subsystem supports the JVM, JS, WasmJs and the same native targets, with one gap: WasmWasi is blocked by an issue in kotlin-logging, which is a dependency problem rather than a design one. The gRPC subsystem supports the JVM only, and the note is emphatic about it, projects with kotlin("jvm") only, with KMP support in development.

The project explains why the table is not uniform. kotlinx.rpc is a KMP library and the aim is to support all available platforms, but it is also a multi-module library, meaning some modules may not support some platforms.

That is an honest framing for a library where the transport and the serialisation are separate concerns from the service definition. The definition, the client and the server are the parts you write against, and they are the parts that work everywhere. The gRPC wire format is the part that has a JVM implementation today, which is consistent with the multiplatform support being in development and offered as a preview.

The gRPC Kotlin Multiplatform support is available for preview, and the README invites feedback on it. There is a longer gRPC integration section further down, and separate sample projects for the gRPC applications, including a grpc-kmp-app.

Wiring it into a Gradle build

The project configuration has three parts, and one of them is easy to miss.

The Gradle plugin that drives code generation goes into the plugins block alongside the Kotlin multiplatform plugin and the serialization plugin.

kotlin
plugins {
    kotlin("multiplatform") version "2.4.0"
    kotlin("plugin.serialization") version "2.4.0"
    id("org.jetbrains.kotlinx.rpc.plugin") version "0.10.4"
}

The second part is the runtime dependencies, and the README notes that Maven Central has to be in the list of your repositories to resolve them. The artifacts are split by role, with a client artifact and a server artifact, a serialization artifact, and the Ktor transport artifacts for the client and the server, plus the Ktor API dependencies themselves with a $ktor_version placeholder for the version.

The third part is the IDE. To ensure that all the IDE features of the compiler plugin work properly on IntelliJ-based IDEs, the project asks you to install the Kotlin External FIR Support plugin. That is a real requirement rather than a nicety, because the generated code is what the IDE is reading to give you the typed service handle, and without the external FIR support the IDE does not see the generated declarations properly.

The repository also has a bom/ directory, so a platform can be aligned to a single version of the library across modules, and a samples/ directory with a simple Ktor app, a Ktor web app, a Ktor Android app, an all platforms app and the two gRPC samples.

Kotlin compatibility and an unusual version scheme

The library supports all stable Kotlin versions starting from 2.2.0, and the README lists them: 2.2.0, 2.2.10, 2.2.20 and 2.2.21, then 2.3.0, 2.3.10, 2.3.20 and 2.3.21, then 2.4.0, 2.4.10 and 2.4.20. A full compatibility checklist lives in the documentation under Versions.

That is a tight coupling to the Kotlin release train, and it is the kind of coupling that comes from being a compiler plugin that lives in the same organisation as the compiler. The practical consequence is that your Kotlin version is not a free choice if you want the RPC plugin, and that an upgrade of Kotlin is likely to pull an upgrade of kotlinx.rpc with it.

The version scheme of the library itself is the more unusual detail. Look at the release list: 0.10.4, then 0.11.0-grpc-190 as the newest, alongside a 0.11.0-grpc-189 from July. The gRPC line is versioned separately from the main line, with a build counter appended, which is a sensible way to ship a subsystem that is not ready to follow the main release cadence.

For a user, the practical reading is that the version you want is in the 0.10 line, that the gRPC work is on its own 0.11 line with a moving counter, and that a build pinned to 0.10.4 gets the gRPC artifacts that are tagged for that release. The repository carries a CHANGELOG.md, and the version numbers in the Gradle examples in the README are 0.10.4, which is the version the documentation was written against.

What is still experimental

The library carries the Kotlin Experimental badge, and it is worth being precise about what that means in practice for a project that is planning around it.

The badge is the standard Kotlin signal that the API may change in a way that breaks source compatibility between minor versions. For a library at version 0.x that is close to a formality, but for a library that installs a compiler plugin and generates code, it is a stronger signal than usual, because the generated code and the runtime have to move together.

The gRPC Kotlin Multiplatform support is explicitly a preview with a request for feedback, which is a narrower and more manageable form of the warning.

The repository layout suggests a project with serious engineering behind it and a young public shape. There is a compiler-plugin/ directory, a gradle-plugin/, a dokka-plugin/ for documentation, a grpc/ directory, a protobuf/ directory, a protoc-gen/ directory, native-deps/, a jpms-check/ directory for module system verification, a detekt/ configuration for static analysis, a karma/ directory for browser based testing, a versions-root/ module, and a youtrack-workflows/ directory alongside a .youtrack/ configuration. There is a qodana.yaml for the code quality tool, a renovate.json5 for dependency updates, and both AGENTS.md and CLAUDE.md, which are the conventions files for the tooling that reads the repository.

The Dockerfile at the root is described as being for local CI builds and is based on a Ktor test image, which is a detail that tells you the test matrix runs against real Ktor servers rather than mocks.

Editorial conclusion

kotlinx.rpc fits a Kotlin Multiplatform team that wants one service definition to work on the JVM, on Kotlin/JS and on native targets, and that is prepared to accept an experimental library in exchange for a shared interface rather than a generated client from a schema. It does not fit a project that needs gRPC today across platforms, since the gRPC module is JVM only and the multiplatform version is still a preview, and it does not fit a team that wants a stable API, because the library is marked Kotlin Experimental. Verify three things before you adopt it: which transport your deployment needs, since kRPC covers JVM, JS, WasmJs and the native targets but not WasmWasi, which is blocked upstream, which serialization format your existing clients speak, and that the Kotlin version you build with is on the supported list, because the library tracks the stable Kotlin releases closely and the Gradle plugin version has to match the runtime artifacts you depend on.

Frequently asked questions

How do I define an RPC service with kotlinx.rpc?

With an interface annotated @Rpc, whose methods are either suspend functions for a single response or plain functions returning a Flow for a streaming call. The server implements the interface, and a compiler plugin invoked through the org.jetbrains.kotlinx.rpc.plugin Gradle plugin generates the client and server code, so the client obtains a typed handle with rpcClient.withService<AwesomeService>().

Which platforms does kotlinx.rpc support?

Core supports the JVM, JS, WasmJs, WasmWasi and the Apple, Linux and Windows native targets. The kRPC subsystem supports the JVM, JS, WasmJs and the native targets, with WasmWasi blocked by an open issue in kotlin-logging. The gRPC subsystem supports the JVM only, for projects using kotlin("jvm") only, with multiplatform support in development and available for preview.

What do I need to add to my Gradle build?

The Gradle plugin id("org.jetbrains.kotlinx.rpc.plugin") version "0.10.4" in the plugins block, Maven Central in the repositories, and the runtime artifacts for the client and server APIs, a serialization module and the Ktor transport artifacts. For IntelliJ based IDEs you also need the Kotlin External FIR Support plugin so the IDE features of the compiler plugin work.

Which serialisation formats are supported?

JSON is used in the quick start examples, and the README notes that protobuf and cbor are provided as well, each as its own serialization module artifact. The serialisation is configured in an rpcConfig block on both the client and the server side, and the configuration has to match.

Which Kotlin versions does kotlinx.rpc work with?

All stable Kotlin versions starting from 2.2.0, which the README lists as 2.2.0 through 2.2.21, 2.3.0 through 2.3.21, and 2.4.0 through 2.4.20, with a full compatibility checklist in the Versions page of the documentation. The library is marked as Kotlin Experimental, so the API can change between minor versions.

Official sources

  1. Kotlin/kotlinx-rpc on GitHub
  2. License: Apache-2.0
  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/kotlin-kotlinx-rpc.svg)](https://hysenlabs.com/projects/kotlin-kotlinx-rpc)

Was this useful?