You know Kotlin. You build Android apps, maybe KMP apps. But what about the backend?
Every app needs a server. An API to fetch data from. A backend to store users, handle payments, send notifications.
You could learn Node.js and Express. Or Python and FastAPI. Or Java and Spring Boot.
Or you could use the Kotlin you already know — and build your backend with Ktor.
What is Ktor?
Ktor is a backend framework built by JetBrains — the same company that created Kotlin. It lets you build web servers, REST APIs, microservices, and web applications using Kotlin.
The key idea: Ktor is Kotlin-native, lightweight, and coroutine-based.
┌─────────────────────────────────────────┐
│ Your Ktor Server │
│ │
│ Routes, authentication, database, │
│ file uploads, WebSockets, caching │
└────────┬──────────┬──────────┬──────────┘
│ │ │
┌────▼────┐ ┌───▼────┐ ┌──▼──────┐
│ Android │ │ iOS │ │ Web │
│ App │ │ App │ │ App │
└─────────┘ └────────┘ └─────────┘
Instead of learning a new language for backend, you use the same Kotlin you already know. Same syntax. Same coroutines. Same data classes.
Why Ktor?
There are many backend frameworks. Here is why Ktor stands out for Kotlin developers:
1. Built for Kotlin
Ktor is not a Java framework with Kotlin support. It was built from the ground up in Kotlin. Everything uses Kotlin features — coroutines, extension functions, DSL builders, data classes.
// This is a complete Ktor server
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/hello") {
call.respondText("Hello from Ktor!")
}
}
}.start(wait = true)
}
No annotations. No XML configuration. No magic. Just Kotlin code.
2. Coroutine-Based
Every request handler in Ktor is a coroutine. This means you can use suspend functions, Flow, and structured concurrency. No callback hell. No thread management.
get("/users/{id}") {
val id = call.parameters["id"]?.toIntOrNull()
// This is a suspend function - no blocking
val user = userRepository.findById(id)
call.respond(user)
}
3. Lightweight and Modular
Ktor does not include everything by default. You add only what you need through plugins:
- Need JSON? Add the serialization plugin.
- Need authentication? Add the auth plugin.
- Need a database? Add Exposed.
- Need WebSockets? Add the WebSocket plugin.
Your server only contains what you actually use. No bloat. No unused features.
4. JetBrains-Backed
Ktor is maintained by JetBrains, the company behind Kotlin, IntelliJ IDEA, and Android Studio. It has dedicated engineers, regular releases, and long-term support.
Ktor vs Other Frameworks
Here is how Ktor compares to popular backend frameworks:
| Ktor | Spring Boot | Express.js | FastAPI | |
|---|---|---|---|---|
| Language | Kotlin | Java/Kotlin | JavaScript | Python |
| Approach | Lightweight, modular | Full-featured, batteries-included | Minimal, middleware-based | Modern, async |
| Configuration | Code DSL | Annotations + YAML | Middleware chain | Decorators |
| Async model | Coroutines | Reactive/Virtual Threads | Event loop | async/await |
| Learning curve | Easy (if you know Kotlin) | Steep | Easy | Easy |
| Startup time | Fast (~1-2 seconds) | Slow (~5-15 seconds) | Fast | Fast |
| Memory usage | Low (~50 MB) | High (~200+ MB) | Low | Low |
| Best for | Kotlin developers, microservices | Enterprise, large teams | Full-stack JS | Data science, APIs |
When to Choose Ktor
- You already know Kotlin
- You want a lightweight server (microservices, APIs)
- You prefer code over annotations and XML
- You want fast startup and low memory usage
- You are building a backend for your mobile app
When to Choose Something Else
- Your team only knows Java → Spring Boot
- You need an enterprise framework with everything built-in → Spring Boot
- You are a full-stack JavaScript developer → Express.js or Next.js
- You are building a data science API → FastAPI
Who Uses Ktor?
Ktor is used by companies of all sizes:
- JetBrains — Uses Ktor internally for many services
- Amazon — Kotlin backend services
- Netflix — Microservices
- DoorDash — API services
- Expedia — Travel platform services
The Kotlin ecosystem is growing fast. In the 2025 JetBrains developer survey, 50% of Kotlin developers use it for backend development. Ktor adoption grew 37% in one year.
Your First Ktor Server
Let’s build a simple server. You need:
- JDK 21 or later
- IntelliJ IDEA (Community or Ultimate)
- Gradle
Step 1: Create the Project
Create a new Gradle project with this build.gradle.kts:
plugins {
kotlin("jvm") version "2.3.0"
application
}
group = "com.kemalcodes"
version = "0.0.1"
application {
mainClass.set("com.kemalcodes.ApplicationKt")
}
repositories {
mavenCentral()
}
val ktorVersion = "3.1.2"
dependencies {
implementation("io.ktor:ktor-server-core:$ktorVersion")
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("ch.qos.logback:logback-classic:1.5.18")
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testImplementation("org.junit.jupiter:junit-jupiter:5.12.2")
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(21)
}
Step 2: Write the Server
Create src/main/kotlin/com/kemalcodes/Application.kt:
package com.kemalcodes
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
module()
}.start(wait = true)
}
fun Application.module() {
routing {
get("/") {
call.respondText("Hello, Ktor!")
}
}
}
Let’s break this down:
embeddedServer(Netty, port = 8080)— Creates a server using the Netty engine on port 8080module()— Configures the application with plugins and routesrouting { }— Defines URL routesget("/")— Handles GET requests to the root pathcall.respondText()— Sends a text response
Step 3: Add Logging
Create src/main/resources/logback.xml:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Step 4: Run the Server
./gradlew run
Open your browser and go to http://localhost:8080. You should see:
Hello, Ktor!
That’s it. Your first Ktor server is running.
Step 5: Write a Test
Create src/test/kotlin/com/kemalcodes/ApplicationTest.kt:
package com.kemalcodes
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.testing.*
import kotlin.test.Test
import kotlin.test.assertEquals
class ApplicationTest {
@Test
fun `root endpoint returns hello`() = testApplication {
application {
module()
}
val response = client.get("/")
assertEquals(HttpStatusCode.OK, response.status)
assertEquals("Hello, Ktor!", response.bodyAsText())
}
}
Run the test:
./gradlew test
The test creates a virtual server (no real HTTP server starts), sends a request, and checks the response. Fast and reliable.
Key Concepts
Before we dive deeper in the next tutorials, let’s understand the core concepts:
Plugins
Ktor uses a plugin system. Each feature is a separate plugin you install:
fun Application.module() {
install(ContentNegotiation) {
json()
}
install(Authentication) {
jwt("auth") { /* config */ }
}
routing {
// routes
}
}
You only install what you need. This keeps your server lightweight.
Routing
Routes map URLs to handler functions. You can group routes, use path parameters, and organize them into separate files:
routing {
route("/api") {
route("/users") {
get { /* list users */ }
post { /* create user */ }
get("/{id}") { /* get user by id */ }
}
}
}
Engine
Ktor supports multiple server engines:
- Netty — Most popular, high performance
- Jetty — Java ecosystem standard
- CIO — Coroutine-based, pure Kotlin
- Tomcat — Traditional Java servlet engine
We will use Netty throughout this series. It is the most popular choice and works great for most use cases.
How Ktor Compares to Ktor Client
If you have been following our KMP Tutorial series, you already know Ktor Client — the HTTP client that runs on Android, iOS, Desktop, and Web.
Ktor Server is the other half of the Ktor project. While the client makes HTTP requests, the server handles them:
┌──────────────┐ ┌──────────────┐
│ Ktor Client │ HTTP │ Ktor Server │
│ (KMP App) │ ────→ │ (Your API) │
└──────────────┘ └──────────────┘
They share concepts like ContentNegotiation, HttpStatusCode, and ContentType. If you know one, the other feels familiar.
Getting Started Options
There are three ways to create a Ktor project:
1. Ktor Project Generator (Web)
Go to start.ktor.io, select your plugins, and download a ZIP file. This is the fastest way to get started.
2. IntelliJ IDEA Plugin
IntelliJ IDEA Ultimate has a built-in Ktor project wizard. Go to File > New > Project > Ktor. This generates the same project as the web generator.
3. Manual Setup (What We Do)
Create a Gradle project yourself and add dependencies manually. This gives you full control and helps you understand every part of the project.
We use the manual approach in this series because it teaches you how everything fits together.
What We Will Build in This Series
Over the next tutorials, we will build a complete backend API. Here is the roadmap:
- What is Ktor? — You are here
- Ktor vs Spring Boot — Detailed comparison
- Project Setup — Application structure and configuration
- Routing — Handling HTTP requests
- Serialization — JSON with kotlinx.serialization
- Database — Exposed ORM with H2
- CRUD Operations — Building a REST API
- Relationships — Advanced queries with Exposed
- File Uploads — Multipart and static files
- Migrations — Database versioning with Flyway
- Authentication — JWT tokens and password hashing
By the end, you will have a production-ready REST API with authentication, database, file uploads, and proper error handling.
Source Code
You can find the source code for this tutorial on GitHub:
github.com/kemalcodes/ktor-tutorial — Branch: tutorial-01-what-is-ktor
What’s Next?
In the next tutorial, we will compare Ktor with Spring Boot in detail. You will learn when to use each framework and understand the trade-offs.
Ktor Tutorial #2: Ktor vs Spring Boot — Which Kotlin Backend?
Related Articles
- Kotlin Tutorial: Complete Series — Learn Kotlin from scratch (prerequisite for this series)
- KMP Tutorial #6: Ktor Client — Networking — Ktor on the client side