Quarkus Qdrant

A Quarkus extension for Qdrant, the open-source vector database. It gives you a QdrantClient to store, search, and manage vectors using the Qdrant REST API.

At a Glance

@Inject
QdrantClient qdrant;

// Create a collection
qdrant.createCollection("docs").vectorSize(384).distance("Cosine").execute();

// Index a point
qdrant.upsert("docs").point(new PointStruct(id, vector, payload)).execute();

// Search
List<ScoredPoint> results = qdrant.search("docs").vector(queryVec).limit(10).execute();

That’s it. No gRPC stubs, no channel management, no heavy dependencies.

Compatibility

We support the three most recent Qdrant minor releases. Today that is 1.18, 1.19 and 1.20.

That is our plan, not a snapshot. When a new minor lands, it joins the window and the oldest one drops out. So the window moves with every Qdrant release, and a version that leaves it stops being supported.

CI runs the full test suite against every version in the window. Nothing in the window is assumed to work. Dev Services starts Qdrant 1.20 by default.

Older servers are out of scope. We do not test them and we do not fix issues against them. 1.10 is the hard floor in any case: search goes through the universal query API (/points/query), which Qdrant added in 1.10.

Newer releases should work, since the response DTOs ignore fields they do not know. If you hit a problem with a fresh Qdrant release, please report it.

Why Quarkus Qdrant?

REST instead of gRPC

The official Qdrant Java client uses gRPC, which brings a heavy dependency chain. This extension uses the Qdrant REST API through the Quarkus REST client instead. Fewer dependencies, faster builds, and native image support without extra configuration.

A real Quarkus extension

This is not a wrapper around an upstream library. It follows the Quarkus extension model: CDI injection, build-time optimization, health checks, and configuration via application.properties. It also allows extensions like quarkus-langchain4j to depend on a proper Quarkus extension rather than pulling in the gRPC client directly.

Fluent API

Every operation uses a builder pattern: qdrant.search("collection").vector(vec).limit(10).execute(). Readable and hard to misuse.

Dev Services

In dev and test mode, a Qdrant container starts automatically. No local install needed.

Dev Services

In dev and test mode, the extension starts a Qdrant container automatically. No configuration needed.

You can pre-create collections at startup:

quarkus.qdrant.devservices.collections.documents.vector-size=384
quarkus.qdrant.devservices.collections.documents.distance=Cosine
quarkus.qdrant.devservices.collections.products.vector-size=128
quarkus.qdrant.devservices.collections.products.distance=Euclid

You can fix the port if you need a stable URL:

quarkus.qdrant.devservices.port=6333

Dev Services is disabled automatically when quarkus.qdrant.host is explicitly set.

Configuring for production

Point to your Qdrant instance:

quarkus.qdrant.host=qdrant.example.com
quarkus.qdrant.port=6333

With API key and TLS:

quarkus.qdrant.host=qdrant.example.com
quarkus.qdrant.port=6333
quarkus.qdrant.api-key=your-api-key
quarkus.qdrant.use-tls=true
quarkus.qdrant.tls-configuration-name=qdrant

The tls-configuration-name points to a named Quarkus TLS configuration for custom trust stores or keystores. If omitted, the default Quarkus TLS configuration is used when available. For example, to configure a custom trust store:

quarkus.tls.qdrant.trust-store.p12.path=/path/to/truststore.p12
quarkus.tls.qdrant.trust-store.p12.password=changeit

Named clients

The extension supports both a default client and named clients. Named clients are necessary when you need to connect to multiple Qdrant instances.

Default client

The default client uses bare properties:

quarkus.qdrant.host=qdrant.example.com
quarkus.qdrant.port=6333

Inject it with no qualifier:

@Inject
QdrantClient qdrant;

Configuring named clients

Named clients use a quoted key in the configuration:

quarkus.qdrant."secondary".host=qdrant-secondary.example.com
quarkus.qdrant."secondary".port=6333
quarkus.qdrant."secondary".api-key=your-api-key
quarkus.qdrant."secondary".use-tls=true

Injecting named clients

Use the @QdrantClientName qualifier:

@Inject
@QdrantClientName("secondary")
QdrantClient secondaryClient;

Each named client is an independent QdrantClient instance with its own connection configuration.

Health check

If you have the quarkus-smallrye-health extension, a readiness check is registered automatically. The health check covers every QdrantClient your application uses (default and named) and reports per-client status. Each client is probed with the same TLS configuration and API key it uses itself.

A readiness response looks like this:

{
  "status": "UP",
  "checks": [
    {
      "name": "Qdrant health check",
      "status": "UP",
      "data": {
        "default": "UP"
      }
    }
  ]
}

Named clients appear as extra keys in data, under the name you configured.

To disable it:

quarkus.qdrant.health.enabled=false

QdrantClient API reference

Operation Example

Create a collection

qdrant.createCollection("name").vectorSize(384).distance("Cosine").execute()

Upsert a single point

qdrant.upsert("name").point(point).execute()

Upsert multiple points

qdrant.upsert("name").points(pointList).execute()

Search

qdrant.search("name").vector(vec).limit(10).execute()

Delete by IDs

qdrant.delete("name").byIds(idList).execute()

Delete by filter

qdrant.delete("name").byFilter(filterMap).execute()

List collections

qdrant.listCollections()

Delete a collection

qdrant.deleteCollection("name")

What’s Next