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

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

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

References