qdrant/qdrant

Qdrant - High-performance, massive-scale Vector Database and Vector Search Engine for the next generation of AI. Also available in the cloud https://cloud.qdrant.io/

30,436 stars Rust 10 components

14 hidden assumptions · 6-stage pipeline · 10 components

Like any codebase, this repository makes assumptions it never checks — most are routine. The ones worth your attention are below.

Stores and searches high-dimensional vectors with metadata filtering at massive scale

Vectors with metadata enter through REST or gRPC APIs, get validated and converted to internal formats, then routed to the appropriate collection shard based on shard key. Within each shard, vectors are inserted into HNSW indexes while payload data is stored in specialized field indexes. Search requests follow the same routing, perform similarity search in HNSW indexes combined with payload filtering, then aggregate results across shards before returning to clients.

Under the hood, the system uses 3 feedback loops, 4 data pools, 4 control points to manage its runtime behavior.

A 10-component repository. 1302 files analyzed. Data flows through 6 distinct pipeline stages.

Hidden Assumptions

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

If grpc.options contains malformed protobuf data or unsupported field types, proto_dict_to_json() will panic or return corrupted JSON data that silently breaks downstream inference processing

Worth your attention first

If a shard is dropped during a multi-step operation (search, update, transfer), the Collection will attempt to route operations to non-existent shards causing panics or data loss without clear error messages

Worth your attention first

If transfers complete out-of-order or WAL sequences get corrupted during transfer, the target shard will have inconsistent data state, causing search results to miss or duplicate points silently

Show everything (11 more)
Scale

Vector dimensions fit within u32 indexing limits and that the HNSW graph can hold all connections in memory, but no bounds checking occurs on dimension count or graph size

If this fails: With vectors having >4 billion dimensions or graphs requiring >available memory, HNSW operations will overflow u32 indices or cause OOM crashes without graceful degradation

lib/segment/src/index/hnsw_index/mod.rs:HnswIndex
Temporal

WAL entries are flushed to disk within 32MB buffer limit or timeout period, but assumes disk I/O will never fail or block indefinitely

If this fails: If disk becomes full or I/O hangs, WAL entries accumulate in memory without being persisted, causing data loss on crash and potential OOM from unbounded memory growth

lib/wal/src/wal.rs:WAL flush batching
Domain

Dense vectors contain finite f32 values (not NaN or infinity) and that distance calculations will produce meaningful results, but no validation occurs on vector contents

If this fails: NaN or infinity values in vectors cause HNSW distance calculations to return NaN, breaking search result ordering and causing segments to return corrupted similarity scores

lib/segment/src/data_types/vectors.rs:VectorInternal::Dense
Resource

The cluster has sufficient nodes and memory to handle the configured shard count, but no capacity planning validation occurs during collection creation

If this fails: Creating collections with shard counts exceeding cluster capacity causes node overload, memory pressure, and degraded search performance across all collections without clear warnings

lib/collection/src/config.rs:shard_count
Contract

Shard keys used in requests always map to existing shards and that the mapping remains stable during multi-shard operations, but no consistency validation occurs

If this fails: If shard mappings change during resharding while searches are in flight, queries will be routed to wrong shards or fail with shard_not_found_error, causing incomplete search results

lib/collection/src/shards/shard_holder.rs:ShardKeyMapping
Environment

gRPC clients send Protocol Buffer messages that conform to the expected schema version and field types, but no version compatibility checking occurs

If this fails: Clients using different protobuf schema versions will send requests with unexpected field layouts, causing silent deserialization failures or type mismatches in service handlers

src/tonic/service.rs:GrpcService
Scale

Payload metadata objects have reasonable field counts and string lengths that fit within indexing limits, but no size validation occurs during insertion

If this fails: Extremely large payload objects (thousands of fields, very long strings) cause index memory bloat and slow insertion/search performance without clear error messages about size limits

lib/segment/src/payload_storage/mod.rs:PayloadIndex
Temporal

Background optimization tasks complete before the next scheduled optimization cycle begins, but no overlap prevention exists

If this fails: If optimization tasks run longer than the scheduling interval, multiple optimizations run concurrently causing resource contention and potentially corrupted segment states

lib/collection/src/optimizers_builder/mod.rs:optimization scheduling
Ordering

Search results from different shards use the same distance metric and scoring scale, allowing direct comparison during merge operations

If this fails: If shards somehow use different distance functions or scoring normalization, merged results will have incorrectly ordered similarity scores, returning the wrong top-k matches to users

lib/collection/src/collection/search.rs:result aggregation
Domain

Point IDs (either u64 or UUID) are unique within a collection and remain stable across updates, but uniqueness is not enforced at the API level

If this fails: Duplicate point IDs in different API calls can overwrite existing points silently, and changing point IDs between updates creates orphaned data that wastes storage

lib/api/src/rest/schema.rs:PointStruct.id
Environment

HTTP clients send JSON payloads with UTF-8 encoding and valid JSON structure, relying on the actix-web framework to handle encoding validation

If this fails: Non-UTF-8 or malformed JSON in requests may cause parsing errors that bubble up as generic 500 errors instead of clear validation messages about encoding issues

src/actix/api/service.rs:QdrantService

Open the standalone hidden-assumptions report for qdrant →

How Data Flows Through the System

Vectors with metadata enter through REST or gRPC APIs, get validated and converted to internal formats, then routed to the appropriate collection shard based on shard key. Within each shard, vectors are inserted into HNSW indexes while payload data is stored in specialized field indexes. Search requests follow the same routing, perform similarity search in HNSW indexes combined with payload filtering, then aggregate results across shards before returning to clients.

  1. API request ingestion — REST endpoints in QdrantService or gRPC endpoints in GrpcService receive requests, validate schemas using validator crate, and convert between JSON/ProtoBuf and internal Rust structures (config: service.host, service.http_port)
  2. Collection routing — Collection.update() or Collection.search() methods determine target shards using ShardKeyMapping, handle shard key-based or hash-based distribution, and route operations to appropriate LocalShard instances [PointStruct → Shard operations]
  3. Shard processing — LocalShard.update_local() writes to WAL for durability, then delegates to underlying segments. LocalShard.search() queries all segments in parallel and merges results [Shard operations → Segment operations] (config: storage.wal.wal_capacity_mb)
  4. Vector indexing — Segment.upsert_point() extracts VectorInternal from points, inserts into HnswIndex using HNSW algorithm, and stores payload data in PayloadIndex with field-specific indexes [VectorInternal → Index updates]
  5. Similarity search — Segment.search() uses HnswIndex.search() to find vector neighbors via graph traversal, applies PayloadIndex filters to candidate points, and returns scored results sorted by distance [SearchRequest → Search results] (config: storage.performance.max_search_threads)
  6. Result aggregation — Collection.search() merges results from multiple shards using a priority queue, applies global limit and offset, and formats final response with requested payload fields [Search results → API response]

Data Models

The data structures that flow between stages — the contracts that hold the system together.

PointStruct lib/api/src/rest/schema.rs
struct with id: PointIdType (u64 or UUID), vector: VectorStructInternal (named vectors map), payload: Option<Payload> (JSON object metadata)
Created from API requests with vectors and metadata, stored in segments with HNSW indexing, retrieved and scored during similarity searches
VectorInternal segment/src/data_types/vectors.rs
enum with Dense(Vec<f32>), Sparse(indices: Vec<u32>, values: Vec<f32>), MultiDense(Vec<Vec<f32>>)
Converted from API vector formats, stored in HNSW or other indexes, used for distance calculations during search
SearchRequest lib/api/src/rest/schema.rs
struct with vector: Vector, limit: usize, offset: Option<usize>, filter: Option<Filter>, params: Option<SearchParams>, with_payload: Option<WithPayloadInterface>
Parsed from REST/gRPC requests, validated and routed to appropriate shards, used to drive HNSW search with optional payload filtering
CollectionConfigInternal lib/collection/src/config.rs
struct with params: CollectionParams (vector configs, distance metrics), optimizer_config: OptimizersConfig, hnsw_config: HnswConfig, quantization_config: Option<QuantizationConfig>
Created when collections are initialized, stored persistently, used to configure segment behavior and optimization schedules
ShardTransfer lib/collection/src/shards/transfer.rs
struct with shard_id: ShardId, from: PeerId, to: PeerId, sync: bool, method: ShardTransferMethod
Created during cluster rebalancing, tracked through transfer state machine, completed when shard data is fully replicated to target peer

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

WAL (Write-Ahead Log) (buffer)
Durably buffers all write operations before they're applied to indexes — ensures crash recovery and provides ordering guarantees for distributed operations
HNSW Index (index)
Multi-layer graph structure storing vectors with navigable connections — provides logarithmic search complexity for similarity queries
Payload Storage (database)
Persistent storage for point metadata with field-specific indexes — enables efficient filtering during search operations
Shard Registry (registry)
In-memory mapping of shard IDs to their locations and replica states — tracks cluster topology and data distribution

Feedback Loops

Delays

Control Points

Technology Stack

Rust (runtime)
Core implementation language providing memory safety and high performance for vector operations and concurrent shard management
Actix-web (framework)
HTTP server framework handling REST API endpoints, request routing, and JSON serialization/deserialization
Tonic (framework)
gRPC server implementation providing high-performance binary protocol support with Protocol Buffer message handling
RocksDB (database)
Persistent storage backend for vector indexes and metadata, providing LSM-tree based disk storage with compression
Tokio (runtime)
Async runtime managing concurrent operations including shard transfers, background optimizations, and client connections
Serde (serialization)
Serialization framework converting between Rust structs and JSON/binary formats for API communication and storage

Key Components

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Related Repository Repositories

Frequently Asked Questions

What is qdrant used for?

Stores and searches high-dimensional vectors with metadata filtering at massive scale qdrant/qdrant is a 10-component repository written in Rust. Data flows through 6 distinct pipeline stages. The codebase contains 1302 files.

How is qdrant architected?

qdrant is organized into 3 architecture layers: API Layer, Collection Management, Storage & Indexing. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through qdrant?

Data moves through 6 stages: API request ingestion → Collection routing → Shard processing → Vector indexing → Similarity search → .... Vectors with metadata enter through REST or gRPC APIs, get validated and converted to internal formats, then routed to the appropriate collection shard based on shard key. Within each shard, vectors are inserted into HNSW indexes while payload data is stored in specialized field indexes. Search requests follow the same routing, perform similarity search in HNSW indexes combined with payload filtering, then aggregate results across shards before returning to clients. This pipeline design reflects a complex multi-stage processing system.

What technologies does qdrant use?

The core stack includes Rust (Core implementation language providing memory safety and high performance for vector operations and concurrent shard management), Actix-web (HTTP server framework handling REST API endpoints, request routing, and JSON serialization/deserialization), Tonic (gRPC server implementation providing high-performance binary protocol support with Protocol Buffer message handling), RocksDB (Persistent storage backend for vector indexes and metadata, providing LSM-tree based disk storage with compression), Tokio (Async runtime managing concurrent operations including shard transfers, background optimizations, and client connections), Serde (Serialization framework converting between Rust structs and JSON/binary formats for API communication and storage). A focused set of dependencies that keeps the build manageable.

What system dynamics does qdrant have?

qdrant exhibits 4 data pools (WAL (Write-Ahead Log), HNSW Index), 3 feedback loops, 4 control points, 3 delays. The feedback loops handle self-correction and retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does qdrant use?

4 design patterns detected: Sharded Architecture, WAL + Index Separation, Pluggable Vector Indexes, Multi-Protocol Gateway.

Analyzed on April 20, 2026 by CodeSea. Written by .