If you already have Qdrant running on your Linux server, the next step is to make it production-ready. That means knowing how to optimize Qdrant for real traffic, including tuning RAM usage, taking proper snapshots, and setting up safe network access.
This guide covers all of Qdrant optimization for real traffic. If you haven't set up Qdrant yet, you can follow this guide on Qdrant installation on a Linux server.
Prerequisites for How to Optimize Qdrant
Before starting, you must make sure:
Qdrant is installed and running via Docker or binary.
You have sudo or root access on your Linux VPS.
curl is installed for API calls.
You're using Ubuntu 22.04 or newer.
Part 1: Understand How Qdrant Uses Memory
Before you start tuning, you need to understand what Qdrant actually does with your RAM. Qdrant has two main storage modes:
In-Memory Storage: All vectors live in RAM. Fastest possible search, but expensive on large collections.
Memmap on-disk Storage: Vectors live on disk and are accessed via OS page cache. When you have enough RAM, it's almost as fast as in-memory.
Important note: Tools like htop or top can be misleading. If they show Qdrant using 10 GB of RAM, it doesn't mean the service requires 10 GB to run; Qdrant aggressively caches data from disk. Unused RAM is wasted RAM, so Qdrant will use what's available.
Check Current Memory Usage:
Bash
# Check Qdrant process memorypsaux|grepqdrant# Check Docker container memorydockerstatsqdrant--no-stream
Check Your Collections Info:
Bash
curlhttp://localhost:6333/collections
Part 2: How to Optimize Qdrant Memory | RAM Tuning
This is the core of how to optimize Qdrant for production. You have three real scenarios to choose from, depending on your setup.
Scenario A: Low RAM, Need Speed (Quantization with On-Disk)
This is the most common setup for a VPS with limited memory. You store the original vectors on disk but keep compressed (quantized) vectors in RAM. Scalar quantization compresses vectors to int8, which means 4x less memory with about 99% accuracy.
This is where a lot of self-hosted vector database setups fail. People configure Qdrant perfectly, then lose everything because they never set up backups. Knowing how to optimize Qdrant isn't just about performance; it's also about making sure your data survives.
Qdrant snapshots are .tar archive files that contain all data and configuration for a collection at a specific point in time. They are not the same as filesystem-level snapshots.
If you want off-site backups, which is highly recommended for production, Qdrant supports S3-compatible storage directly as of v1.10.0:
YAML
1storage:2snapshots_config:3snapshots_storage: s345s3_config:6bucket: your-bucket-name7region: us-east-18access_key: your_access_key9secret_key: your_secret_key10# For MinIO or other S3-compatible storage:11endpoint_url: https://your-minio-server:9000
Part 4: How to Optimize Qdrant Network Security
By default, Qdrant binds to 0.0.0.0, which means it listens on all network interfaces, including your public IP. Anyone who finds port 6333 open on your server can read or delete your data.
To learn how to optimize Qdrant network security, follow the steps below:
Step 1: Bind Qdrant to Localhost Only
This is the most important security step for Qdrant. Edit your config.yaml file:
YAML
1service:2host:127.0.0.1# Only accept connections from localhost3http_port:63334grpc_port:63345api_key:"your_strong_api_key_here"6read_only_api_key:"your_read_only_key_here"
Even if you've bound Qdrant to localhost, you can block the port at the firewall level as a second layer of security:
Bash
# Enable UFW if not already enabledsudoufwenable# Allow SSH first (important: do this before enabling UFW)sudoufwallowssh# Block Qdrant ports from external accesssudoufwdeny6333/tcpsudoufwdeny6334/tcp# Check rulessudoufwstatus
If you have a trusted app server on the same network and need to allow it specifically, you can use:
Bash
# Allow only from a specific IP sudoufwallowfrom10.0.0.5toanyport6333
Step 4: Put Qdrant Behind Nginx
If your app needs to expose Qdrant queries to external clients, for example, a public-facing search API, never expose Qdrant directly. Instead, put Nginx in front of it:
Install Nginx:
Bash
sudoaptupdatesudoaptinstallnginx-y
Create a new Nginx config:
Bash
sudonano/etc/nginx/sites-available/qdrant
Paste this config:
Bash
server{listen443ssl;server_nameqdrant.yourdomain.com;ssl_certificate/etc/letsencrypt/live/qdrant.yourdomain.com/fullchain.pem;ssl_certificate_key/etc/letsencrypt/live/qdrant.yourdomain.com/privkey.pem;# Only allow search endpoint (read-only exposure)location/collections{# Validate API keyif($http_api_key!="your_read_only_key"){return403;}proxy_passhttp://127.0.0.1:6333;proxy_set_headerHost$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;}# Block everything elselocation/{return403;}}# Redirect HTTP to HTTPSserver{listen80;server_nameqdrant.yourdomain.com;return301https://$host$request_uri;}
Not every deployment needs Qdrant exposed to the public internet. In most cases, the best way of how to optimize Qdrant for security is to keep it completely private and let your app layer handle all external requests.
Keep Qdrant private when:
Your app server is on the same machine as Qdrant.
You're using a private network or VPN between services.
You're running a RAG pipeline where only your backend queries Qdrant.
You don't want to manage public-facing certificates and API exposure.
Architecture for private setup:
HTML/XML
Internet → Your App (public port 443) → Qdrant (127.0.0.1:6333, private)
Your app handles auth, rate limiting, and business logic, then queries Qdrant internally over localhost. This is the safest and most common production pattern.
Only expose Qdrant publicly when:
You need multiple services on different servers to query Qdrant directly.
You're building a shared search infrastructure for a team.
Your app is on a different server with no private network option.
In those cases, use the Nginx reverse proxy setup from Part 4, always with HTTPS and API key validation.
Part 6: Complete Qdrant Config YAML File
Here is a full production-ready configuration file that keeps everything together. This is how to optimize Qdrant looks in a real config.yaml:
YAML
1# /path/to/qdrant/config/production.yaml23log_level: INFO45storage:6# Path where Qdrant stores data7storage_path: /qdrant/storage89# Path for snapshots10snapshots_path: /qdrant/snapshots1112# Temp path for snapshot creation13temp_path: /tmp1415# Optional S3 snapshot storage16# snapshots_config:17# snapshots_storage: s318# s3_config:19# bucket: my-qdrant-backups20# region: us-east-121# access_key: KEY22# secret_key: SECRET2324service:25# Bind to localhost only — change to 0.0.0.0 only if behind a secure reverse proxy26host:127.0.0.127http_port:633328grpc_port:63342930# Always set an API key in production31api_key:"replace_with_a_strong_random_key"32read_only_api_key:"replace_with_a_separate_read_only_key"3334# Enable CORS only if your frontend queries Qdrant directly (not recommended)35enable_cors:false3637# Enable TLS if you're not using a reverse proxy38# enable_tls: true3940# Optional TLS config41# tls:42# cert: /tls/cert.pem43# key: /tls/key.pem
The ulimits setting prevents the too many open files error that can occur with large collections.
Part 7: Verify Your Qdrant Optimization Setup
Run these checks to confirm everything is working correctly.
Check Qdrant is running:
Bash
curlhttp://localhost:6333/healthz
Expected output:
HTML/XML
healthz check passed
Test API key works:
Bash
# This should be rejected (no key)curlhttp://localhost:6333/collections# This should work (with key)curlhttp://localhost:6333/collections\-H'api-key: your_strong_api_key_here'
Check Port is Not Exposed Externally: From another machine or using an online port scanner, confirm port 6333 is closed:
Bash
nc-zvYOUR_SERVER_IP6333
Check Snapshot Location:
Bash
# Inside Dockerdockerexecqdrantls/qdrant/snapshots/# Or check your mounted volumels/path/to/qdrant_snapshots/
Look at the config section in the response; it shows the on_disk and quantization settings you applied.
When to Upgrade Your Qdrant Server
If you're noticing the following things, a small VPS is no longer the right option:
Slow query times even with quantization enabled.
Frequent memory pressure, OOM kills, and swap usage.
Growing collections with millions of vectors.
High concurrent query load.
At this stage, moving to a dedicated server hosting gives you predictable performance, dedicated CPU and RAM, and much faster NVMe storage for on-disk collections.
Moving from a shared VPS to a dedicated server is one of the best performance improvements you can make for a production Qdrant deployment, especially when your collections start growing past a few million vectors.
For AI-specific workloads involving embedding generation, reranking, or LLM inference alongside Qdrant, you should also look into purpose-built AI hosting infrastructure that gives you GPU access alongside your vector database.
Conclusion
At this point, you have learned how to optimize Qdrant for your specific RAM and disk situation, build a reliable snapshot and backup habit before you need it, and make sure Qdrant is never accidentally left open to the internet.
We hope you enjoy this guide.
No, Qdrant does not have a built-in scheduler for snapshots on self-hosted setups. You need to use the API with a system cron job, as shown in this guide. Qdrant Cloud has a built-in backup scheduler.
Yes, if you expose port 6333 publicly without an API key, anyone can access your data. Always bind to 127.0.0.1 or use a firewall rule to block external access.
Qdrant saves data to disk all the time, so if it shuts down properly, your data is usually safe. But if there’s a hardware failure or disk corruption and no snapshot, you can lose data. Always take regular snapshots.
We use cookies to run PerLod and to understand how the site is used. You can accept everything, or open Manage to turn individual categories off. Cookie policy.