If you build on the JVM and want to use Qdrant, the official client is io.qdrant:client — and it's built for Java. Every call returns a ListenableFuture, requests are assembled with protobuf builders, and it drags a gRPC/Netty stack onto your classpath. From Kotlin, that means fighting the language: // official Java client, from Kotlin val future: ListenableFuture = client.upsertAsync("articles", points) val result = future.get() // block, or bolt on a future→coroutine bridge yourself Enter fullscreen mode Exit fullscreen mode You reach for coroutines, you get futures. You want a DSL, you get protobuf builders. Meet Kdrant Kdrant is the client you'd actually want to write Kotlin against: Coroutine-first — every operation is a suspend function, with cooperative cancellation and timeouts Type-safe DSLs for collections, points, payloads, and filters Small footprint — a pure-Kotlin REST engine on Ktor + kotlinx-serialization; no gRPC, Netty, or protobuf Typed errors — a sealed KdrantException you can handle exhaustively It's stable (1.1.0, SemVer) and published to Maven Central under io.github.nacode-studios. Quick start Requires JDK 17+. One dependency: dependencies { implementation("io.github.nacode-studios:kdrant-transport-rest:1.1.0") } Enter fullscreen mode Exit fullscreen mode Spin up Qdrant locally: docker run -p 6333:6333 qdrant/qdrant Enter fullscreen mode Exit fullscreen mode Connect, create a collection, upsert, search: val qdrant = Kdrant(host = "localhost", port = 6333) { apiKey = System.getenv("QDRANT_API_KEY") // omit for a local, unauthenticated node requestTimeout = 5.seconds } qdrant.use { client -> client.createCollection("articles") { vector { size = 1_536; distance = Distance.COSINE } } client.upsert("articles", wait = true) { point(id = 1) { vector(embedding) // your List from any embedding model payload("title" to "Introduction", "lang" to "en", "year" to 2026) } } val hits = client.search("articles") { query(queryVector) limit = 5 filter { must { "lang" eq "en" } } } } Enter fullscreen mode Exit fullscreen mode Kdrant stores and searches vectors you already have — it does not generate embeddings. A filter DSL that reads like Kotlin Qdrant's full filtering model, expressed declaratively: val query = filter { must { "lang" eq "en" "year" gte 2024 "price" between 10.0..99.0 } should { matchAny("tag", "featured", "promo") geoRadius("location", GeoPoint(lon = 13.40, lat = 52.52), radius = 5_000.0) } mustNot { "archived" eq true } } Enter fullscreen mode Exit fullscreen mode Decode results straight into your types @Serializable data class Article(val title: String, val lang: String) val articles: List> = qdrant.searchAs("articles") { query(queryVector); limit = 5 } val first: Article? = articles.firstOrNull()?.payload Enter fullscreen mode Exit fullscreen mode Hybrid search (dense + sparse) The modern /points/query engine is fully supported. Fuse several prefetch sources with Reciprocal Rank Fusion for true dense + keyword hybrid search: val hits = qdrant.search("articles") { prefetch { query(denseVector); using = "text"; limit = 50 } prefetch { querySparse(indices, values); using = "keywords"; limit = 50 } rrf() // or dbsf() limit = 10 } Enter fullscreen mode Exit fullscreen mode recommend / discover / context, grouped and batch search, multi-vectors, and a Flow-based scroll are all there too. Building RAG? It plugs in. Kdrant ships first-class integrations so you don't wire it by hand: Spring Boot starter — an auto-configured QdrantClient bean Spring AI — implements VectorStore LangChain4j — implements EmbeddingStore There's a runnable example-rag service (ingest → embed → store → retrieve) with a docker-compose for Qdrant, so you can see it end to end. The honest tradeoff For raw throughput and streaming, gRPC/HTTP2 still wins — reach for the official client when that is your bottleneck. Kdrant trades that for idiomatic Kotlin and a much smaller footprint: Kdrant Official io.qdrant:client Wire protocol REST over Ktor CIO gRPC (HTTP/2) Heavy deps none — pure Kotlin shaded Netty, protobuf, gRPC, Guava Added footprint ~3–5 MB ~15–20 MB API style suspend + Flow, DSL ListenableFuture, protobuf builders GraalVM native friendly needs gRPC/Netty/protobuf config For typical RAG and embedding-search workloads, that's a trade I'll take. Try it ⭐ Repo: https://github.com/NaCode-Studios/Kdrant 📦 Maven Central: io.github.nacode-studios:kdrant-transport-rest:1.1.0 📖 API docs: https://nacode-studios.github.io/Kdrant/ 🪪 Apache-2.0 Feedback is very welcome — especially on API ergonomics. If there's something you'd want from a Kotlin-native Qdrant client, open an issue and let's talk.
Kdrant: an idiomatic, coroutine-first Kotlin client for Qdrant
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.