DEV Community

리브미
리브미

Posted on

pgvector vs Pinecone vs Qdrant: When Is a Dedicated Vector Database Actually Worth It?

If you already run Postgres and your corpus is in the low millions of vectors, pgvector is usually the right first choice — one less system to operate, and your filters, joins, and transactions stay in one place. You reach for a dedicated vector database like Pinecone or Qdrant when recall at high query volume, horizontal scale, or operational hand-off starts to hurt inside Postgres. The wrong reason to switch is "everyone else uses a vector DB."

I've shipped retrieval features on all three. What follows is how I actually decide, not a feature matrix scraped from landing pages.

What are you really choosing between?

These three products are not the same category, and treating them as interchangeable is the first mistake.

pgvector is a Postgres extension. It adds a vector column type and approximate-nearest-neighbor indexes (IVFFlat and, in more recent versions, HNSW) to a database you probably already run. It is open source and lives inside your existing Postgres instance.

Pinecone is a fully managed, closed-source vector database delivered as a cloud service. You don't run it; you call an API. Its serverless model separates storage from compute so you're not sizing pods by hand the way the older architecture required.

Qdrant is an open-source vector database written in Rust. You can self-host it (Docker, Kubernetes) or use Qdrant Cloud. It's built around vectors plus rich payload filtering as a first-class concern.

The takeaway: pgvector is a feature of a database you have; Pinecone is a service you rent; Qdrant is a system you can either run or rent.

When is pgvector enough?

For most teams starting out, it is. If your data already lives in Postgres, keeping embeddings in the same database means a retrieval query can filter on tenant_id, join to a users table, and respect the same transaction — no dual-write, no sync job, no "why is the vector store stale" incident at 2 a.m.

A minimal setup looks like this:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id        bigserial PRIMARY KEY,
  tenant_id bigint NOT NULL,
  content   text,
  embedding vector(1536)
);

-- HNSW index for cosine distance
CREATE INDEX ON documents
  USING hnsw (embedding vector_cosine_ops);
Enter fullscreen mode Exit fullscreen mode

Querying is just SQL, so you combine metadata filters and similarity in one statement:

SELECT id, content
FROM documents
WHERE tenant_id = 42
ORDER BY embedding <=> $1   -- <=> is cosine distance
LIMIT 5;
Enter fullscreen mode Exit fullscreen mode

Where it strains: at higher volumes, the pre-filter-vs-index interaction matters. A restrictive WHERE clause combined with an ANN index can force Postgres to over-scan to fill your LIMIT, hurting recall or latency, and tuning hnsw.ef_search becomes a real exercise. You're also sharing CPU and memory with your transactional workload — a heavy embedding backfill can contend with production traffic. And you own index build times, VACUUM behavior, and memory sizing yourself.

The takeaway: pgvector wins on operational simplicity and query expressiveness until vector search starts competing with your OLTP workload for resources.

When do you actually need Pinecone or Qdrant?

The honest trigger is usually one of three things: scale past what a single Postgres box serves comfortably, query concurrency that demands isolation from your primary database, or a team that wants search to be someone else's operational problem.

Pinecone's pitch is that you never think about the index. No servers, no VACUUM, no HNSW parameters exposed as your problem — you upsert and query. That's genuinely valuable for a small team without a database specialist. The cost is real lock-in: it's closed source and cloud-only, so there's no self-host escape hatch, and your embeddings and metadata live in a vendor you can't run yourself. Pricing is consumption-based, which is efficient at low volume but requires modeling as you grow.

Qdrant sits in between. You get a purpose-built engine with strong metadata filtering, quantization options to cut memory, and the freedom to self-host or use their cloud. The tradeoff is that self-hosting means you're back to running a stateful distributed system — sharding, replication, backups, upgrades. You've traded Postgres operations for Qdrant operations, which is only a win if the vector workload justifies a dedicated system.

Using Qdrant from Python is straightforward:

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

client = QdrantClient(url="http://localhost:6333")

client.recreate_collection(
    collection_name="documents",
    vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)

client.upsert(
    collection_name="documents",
    points=[
        PointStruct(id=1, vector=embedding, payload={"tenant_id": 42}),
    ],
)

hits = client.search(
    collection_name="documents",
    query_vector=query_embedding,
    limit=5,
)
Enter fullscreen mode Exit fullscreen mode

The takeaway: a dedicated vector DB earns its keep when search scale or isolation is a first-order requirement — not when it's a nice-to-have.

How do they compare at a glance?

pgvector Pinecone Qdrant
Category Postgres extension Managed cloud service Open-source DB (self-host or cloud)
You operate it? Yes (it's your Postgres) No Yes if self-hosted, no if cloud
Source model Open source Closed source Open source
Metadata + joins Full SQL, joins, transactions Metadata filters only Rich payload filtering
Ops burden Shared with your OLTP DB Lowest — nothing to run Dedicated system to run (if hosted)
Best when You already run Postgres, ~millions of vectors You want zero ops You want a purpose-built engine you control
Main drawback Contends with primary DB at scale Lock-in, cloud-only Self-hosting is a real workload

Treat this as a starting hypothesis, then benchmark on your own data — recall and latency depend heavily on dimension count, filter selectivity, and index parameters, none of which a table can capture.

What does the switch actually cost you?

The migration itself is rarely the hard part — re-embedding and bulk-loading a few million vectors is a batch job. The recurring cost is a second system in your architecture: another thing to monitor, back up, secure, keep in sync with your source of truth, and reason about during incidents.

That's the build-vs-buy calculus. Staying on pgvector keeps your surface area small but caps your ceiling. Moving to Pinecone buys away operations at the price of lock-in and a usage bill that scales with success. Moving to self-hosted Qdrant keeps you in control and open source but hands you a distributed database to run. There's no free option — only the tradeoff that fits your team's skills and your workload's real shape.

The takeaway: the meaningful cost of a dedicated vector DB is ongoing operational surface area, not the one-time migration.

Bottom line

Start with pgvector if you already run Postgres and your vector count is in the low millions — you'll ship faster and debug less. Move to Pinecone when you want search to be a managed API and you can accept closed-source lock-in in exchange for near-zero operations. Choose Qdrant when you want a purpose-built, open-source engine and either have the appetite to run it or are happy to pay for their cloud. Whatever you're leaning toward, benchmark on your own corpus with realistic filters before committing — the right answer is workload-specific, and it changes as you grow.

Top comments (1)

Collapse
 
mads_hansen_27b33ebfee4c9 profile image
Mads Hansen

The “benchmark your own corpus” line is the decision rule that deserves the most weight. Vector count alone is a weak migration trigger.

I would define a switch threshold as an SLO and run the candidate system in shadow mode against production-shaped queries:

  • recall@k against an exact-search sample
  • p95/p99 latency split by tenant and filter selectivity
  • ingestion-to-search visibility lag
  • cost per million queries plus idle cost
  • impact on OLTP CPU, cache hit rate, WAL and replica lag
  • failure behavior during reindexing, node loss and backfills

The consistency model matters too. Moving away from Postgres introduces a second truth boundary, so every benchmark should include deletes, permission changes and tenant moves—not only fresh inserts. “Fast but stale for revoked access” is a security regression, not a search tradeoff.

A practical migration gate is: dedicated search wins the measured SLO by enough margin to pay for dual-write reconciliation, backup/restore, access-control parity and incident ownership. Until then, pgvector’s transactional locality is doing more work than the latency chart shows.