Skip to main content
  1. Blog/

Lessons Learned: 3 Years of Qdrant on Kubernetes for Product Recommendations

6 mins·
Development Development Qdrant Datascience
Table of Contents

Since 2023, I have served as a Tech Lead and consultant for a product providing large-scale recommendation solutions. A substantial part of our stack relies on Qdrant and Kubernetes. Over the years, we’ve handled millions of vectors and survived more than a few unexpected challenges. If there is one thing I’ve learned, it’s that in the world of vector databases, data science needs a rock-solid operational foundation to prevent lost opportunities. Understanding database internals and Kubernetes plumbing is what transforms nighttime pager alerts into fiction.

Running a stateful, high-performance engine like Qdrant in a dynamic environment like K8s isn’t a “set-and-forget” operation. Here is a deep dive into the reality of keeping a vector store healthy, fast, and cost-effective when your business depends on it.

Pillar I: The Kubernetes Infrastructure Layer
#

When you first deploy Qdrant, the Helm chart makes everything look simple. However, K8s and Rust-based engines don’t always speak the same language regarding resource management.

The OOM-Kill Spiral
#

One of our biggest early hurdles was the OOM-Kill Spiral. In a recommender system, you face constant ingestion and optimization. If your memory limits are tuned too tightly to your steady-state usage, the engine will eventually hit a limit during a heavy indexing spike and be terminated by the kernel.

The real pain starts on reboot. Qdrant must replay its Write-Ahead Log (WAL) and map index files into memory. This “Cold Start” creates a massive memory spike. If the recovery itself hits the K8s limit, the pod is killed again. You end up in a CrashLoopBackOff that won’t resolve until you manually bump the limits. In the worst-case scenario, constant OOM-killing during a sensitive application state results in a corrupted database. This leaves the operator with two grim choices: re-ingest an entire collection (causing a substantial outage) or attempt a hard-restore of the persistent storage.

Since Qdrant does not natively “throttle” itself based on K8s resource limits, the burden falls on the operator. Providing a generous safety buffer and constantly monitoring CPU, disk, and memory consumption through robust observability and alerting is the only way to avoid this stress.

Tuning for Stability
#

We also learned to stop trusting the default terminationGracePeriodSeconds. If K8s sends a SIGKILL while Qdrant is still flushing memtables to disk, you are essentially inviting WAL corruption. We bumped ours to 60–120 seconds to allow the engine to park safely.

Embracing Helm Chart Update Sequence changes
#

Regarding deployment, we eventually moved to Parallel updates in our StatefulSet, accepting the temporary downtime rather than overriding the chart to keep legacy (orderedFirst) settings.

Managing the Cluster Consensus
#

If your readiness probes aren’t perfect, you risk taking down too many nodes at once and breaking RAFT quorum. If you lose that consensus, the cluster goes “brain-dead.” In these moments, you’ll find yourself manually interceding with the /cluster API to hunt down and eject “Ghost Nodes” (stale IPs) to restore order. It is often a last-resort maneuver to keep the cluster alive before being forced into a full re-ingestion.

Pillar II: Data Modeling & Schema Strategy
#

Architectural choices you make in year one will either save you or haunt you in year three.

Collection Architecture vs. Bloat
#

A common mistake is over-complicating the collection strategy. You might be tempted to create a collection per country or per tenant—don’t. The overhead of managing thousands of HNSW graphs and their associated internal threads will eventually drive resource consumption beyond your capacity.

Events like schema evolution or costly operations (such as grouping) will quickly consume whatever CPU reserves you have left. We found that a single, large collection using a country_id payload filter is far more efficient and sustainable.

Schema Evolution & Point ID Optimization
#

Unlike a pure document store, you cannot easily change a payload field from a keyword to an integer once the collection is live. The same rigid rules found in other document databases apply here.

However, the most impactful optimization we found involved the Point IDs. We moved from UUIDs to 64-bit Integers. They are significantly more memory-efficient and faster for the internal lookup tables Qdrant maintains.

Furthermore, we learned to stop treating the Point ID as an arbitrary internal value. If you can use the Point ID for basic retrieval—for example, by setting the ID to the product’s SKU—you should. Relying on the Point ID for direct lookups is always faster and cheaper than relying on payload filters. It effectively grants you the performance of a Key-Value store for free, bypassing the compute-heavy filtering engine entirely.

Pillar III: Performance & Optimization
#

In e-commerce, latency matters for many reasons—from UX and real-time bidding to the simple cost of missed opportunities. But high-performance vector search is only as fast as its metadata filters.

The Indexing Foundation
#

In a recommender, you almost never perform a “pure” vector search. You are almost always filtering for stock status, regional availability, or categories. If you don’t index those payload fields, Qdrant is forced to perform a brute-force scan of the metadata. Payload indexing is non-negotiable. The moment we properly indexed our filters, our P99s dropped from hundreds of milliseconds to the single digits.

RAM Management & Frequent Updates
#

For cost-effective scaling, Quantization (Scalar or Binary) was our primary lever. It allowed us to reduce our memory footprint by over 4x with negligible impact on recall.

Equally important was how we handled high-churn data. Product prices and stock status change every minute; vectors change much less frequently. We learned to use Partial Payload Updates (PATCH) religiously. A full PUT request for a price change forces Qdrant to re-evaluate the entire point. By patching only the metadata, we avoided the heavy CPU cost of unnecessary HNSW re-indexing.

Pillar IV: Operational Resilience & SRE
#

Maintenance is where true “lessons learned” are forged.

Monitoring the Pulse: The /issues Endpoint
#

If you aren’t monitoring the /issues endpoint, you’re flying blind. It acts as an “Active Advisor,” flagging when the optimizer is falling behind or when you’ve forgotten a critical payload index.

We also had to work around the lack of traditional Read Replicas. Since Qdrant scales replicas internally, heavy ingestion can starve search queries of CPU. We used distributed sharding and higher replication factors to ensure that indexing new products didn’t spike latencies for shoppers.

Low-Tech Wins
#

Finally, application-level caching remains the ultimate hero. Before a query ever hits the database, a simple Redis cache for common recommendation sets can offload 30–40% of traffic. It is the most effective way to protect your infrastructure during sudden traffic surges.

Conclusion: The Three-Year Verdict
#

Operating Qdrant for three years has shifted our focus from “how do we search?” to “how do we scale?” The engine is remarkably capable, but it requires respect for its underlying mechanics—the HNSW graph, the RAFT consensus, and the way it interacts with the Linux kernel via Kubernetes.

If you’re just starting, prioritize your payload indexes, use your Point IDs strategically to avoid unnecessary filtering, and never underestimate the power of a simple cache. Your P99s (and your sleep schedule) will thank you.

Related

Fuzz Testing in Golang
15 mins
Development Golang
Containers or FaaS? Don't worry, you are OK!
6 mins
Development Cloud
How to pass the Amazon Certified Solution Architect Associate Exam
6 mins
Development Cloud
Hugo Continous Integration and Deployment
3 mins
Development Hugo Ci Docker
Data Serialization Frameworks in Java
16 mins
Development Java Avro
Coupling Go Services with Java Using Protocol Buffers over MQTT
4 mins
Development