Ktor
Ktor is JetBrains' framework for building asynchronous servers and HTTP clients in Kotlin. It is small and explicit: an application is a Kotlin function that installs plugins and defines routes with a type-safe DSL, and every request is handled in a coroutine, so I/O never blocks threads. There is no classpath scanning or annotation magic — what a Ktor application does is visible in its code.
Ktor has two halves sharing one design. Ktor Server runs on engines such as Netty or CIO to serve HTTP and WebSocket APIs. Ktor Client is a multiplatform HTTP client used on the JVM, Android, iOS, desktop, and the web — a cornerstone of Kotlin Multiplatform apps. Teams choose Ktor for lightweight services, coroutine-native code, and a codebase that reads like Kotlin rather than like a framework.
TL;DR
- A Ktor server is an engine (Netty, CIO, Jetty) running one or more modules (
Application.module()). - Behavior comes from plugins:
ContentNegotiation,Authentication,StatusPages,CORS,RateLimit,CallLogging, and more. - Routes are declared with a DSL (
routing { get("/orders/{id}") { ... } }). - Each request runs in a coroutine; use suspending libraries or
Dispatchers.IOfor blocking calls. testApplicationruns the app in memory for fast, realistic tests.- Ktor Client is multiplatform, with engines per platform and the same plugin model.
Quick Example
A JSON API with JWT authentication and consistent error responses:
Testing it without a network port:
Core Concepts
Engines, Modules, and Configuration
Plugins
Nearly every feature is a plugin, installed at the application or route level:
Custom plugins hook into the request pipeline with createApplicationPlugin or createRouteScopedPlugin.
Coroutines and Request Handling
Each call runs in a coroutine scoped to the request: when the client disconnects or the server stops, work started in that scope is canceled. Suspending libraries — Ktor Client, R2DBC drivers, Exposed with coroutine support — keep threads free. Blocking libraries such as JDBC must run in withContext(Dispatchers.IO), or they stall the engine's event loop threads. See Kotlin Coroutines and Structured Concurrency.
Dependency Injection
Ktor does not require a DI container. Small services pass dependencies to modules as parameters; larger ones use Koin or Ktor's own dependency injection plugin. Passing dependencies explicitly keeps modules easy to test.
Ktor Client
Engines include CIO and OkHttp on the JVM and Android, Darwin on Apple platforms, and JS/Wasm engines in browsers, so shared Kotlin code can call APIs on every platform.
Deployment
- Fat JAR: the Ktor Gradle plugin's
buildFatJartask produces a runnable JAR. - Container images: build with the Ktor plugin's Docker tasks, Jib, or a Dockerfile on a JRE base image.
- Native images: GraalVM native image support for fast startup with the CIO engine, with some library constraints.
- Graceful shutdown: configure shutdown grace periods so in-flight requests complete during rolling deploys.
Ktor Compared With Spring Boot
See Spring Boot.
Best Practices
Organize Routes by Feature
Split routes into extension functions per feature (fun Route.orderRoutes(service: OrderService)) so modules stay small and dependencies explicit.
Centralize Error Handling
Use StatusPages to map domain exceptions to HTTP responses consistently, including problem-details JSON, instead of try/catch in every handler.
Keep Blocking Work Off Engine Threads
Wrap JDBC and other blocking calls with Dispatchers.IO or use non-blocking drivers.
Test Through testApplication
Exercise real routing, plugins, and serialization in memory, replacing external dependencies with fakes.
Common Mistakes
Blocking the Engine
Forgetting Serialization Annotations
Launching Work in GlobalScope
FAQ
What is Ktor?
A Kotlin framework from JetBrains for building asynchronous HTTP servers and multiplatform HTTP clients, based on coroutines, plugins, and a routing DSL.
Is Ktor production-ready?
Yes. It is used in production by JetBrains and many other companies. It provides the essentials — serialization, authentication, metrics, WebSockets, testing — while leaving architecture choices to you.
Should I use Ktor or Spring Boot?
Ktor suits lightweight, coroutine-native services and teams that prefer explicit code. Spring Boot suits teams wanting a large integrated ecosystem and conventions. Both are solid choices for Kotlin backends.
Can Ktor use JDBC databases?
Yes, through libraries such as Exposed, jOOQ, or plain JDBC, running blocking calls on Dispatchers.IO. Non-blocking options include R2DBC drivers.
What is Ktor Client used for?
Making HTTP requests from Kotlin on the JVM, Android, iOS, desktop, and web, with the same API and plugins everywhere — especially in Kotlin Multiplatform projects sharing networking code.
Related Topics
- Kotlin — The language
- Kotlin Coroutines and Structured Concurrency — The concurrency model under Ktor
- Kotlin Multiplatform — Sharing the Ktor client across platforms
- Spring Boot — The other major JVM framework
- REST APIs — Designing the APIs Ktor serves
- JWT — Token authentication