VectorOpsReport
A tiered pink gear-edged cylinder rises above a dotted grid platform beside a bead-covered disc and a light blue cube, evoking layered vector database nodes.
Comparison

pgvector vs Pinecone Comparison: Cost per Query at Target Recall

A pgvector vs Pinecone comparison for teams putting retrieval in production: architecture, filtering behaviour, what the vendor benchmarks actually measured, and the one metric that decides it.

By VectorOpsReport Editorial · · 6 min read

The question behind every pgvector vs Pinecone comparison is operational, not philosophical: the retrieval step of a RAG service is about to take production traffic, someone has to pick a store, and the p99 of that store will be the p99 of the product. They differ in where the index lives, who pays for RAM, what a metadata filter does to recall, and how the bill scales with load. This piece works through those differences from the vendors’ docs and benchmarks, and flags every vendor benchmark as one.

What each one is, mechanically

pgvector is a PostgreSQL extension. It adds a vector column type (up to 16,000 dimensions for storage, 2,000 for an index; halfvec indexes to 4,000), six distance operators including cosine <=>, inner product <#> and L2 <->, and two approximate indexes: HNSW and IVFFlat. HNSW takes m (default 16) and ef_construction (default 64) at build time and hnsw.ef_search (default 40) at query time. IVFFlat takes lists (rows/1000 up to 1M rows, sqrt(rows) beyond) and ivfflat.probes (start at sqrt(lists)). The current release is v0.8.6. The graph sits in Postgres shared buffers, so the operator’s job is keeping the index in RAM; see memory sizing for a vector database for how to size that.

Pinecone serverless is a managed service with storage and compute on separate paths. Records live in object storage as immutable files the docs call slabs, recent writes sit in an in-memory memtable that every read checks first, and a query router picks the slabs to search per namespace. Nothing about the index is tunable; there is no m, no ef, no probes. Limits worth knowing from the database limits page: 20,000 dimensions, 40 KB of filterable metadata per record, top_k up to 10,000, 1,000 records per upsert, and a rate cap of 100 requests per second per namespace on every plan. Namespaces per index run from 100 on Starter to 100,000 on Standard and Enterprise.

pgvector’s default index is Malkov and Yashunin’s HNSW graph, with logarithmic search scaling. The disk-resident alternative, DiskANN, serves a billion points from 64 GB of RAM plus SSD at 95%+ 1-recall@1 and underlies the StreamingDiskANN index in pgvectorscale. The index families are compared in HNSW vs IVF: tradeoffs compared.

The metric that matters: cost per query at target recall

QPS headlines are not comparable across these two, because they bill on different axes. Use:

cost_per_query = monthly_spend / monthly_queries, at recall@k >= target

with recall measured against exhaustive search on a golden query set, never assumed.

For pgvector, monthly_spend is an instance price and does not move with query volume until the box saturates. For Pinecone, spend is read units, and per the cost docs a query costs 1 RU per GB of namespace size with a 0.25 RU floor; top_k and include_metadata do not change it. Writes cost 1 WU per KB with a 5 WU minimum. On the Standard plan that is $16 to $18 per million RUs, $4 to $4.50 per million WUs, $0.33 per GB-month of storage, and a $50 monthly minimum. Starter is free with 2 GB, 1M RUs and 2M WUs a month.

The arithmetic that follows from those figures: a 10 GB namespace costs 10 RUs per query, so one million queries a month is about $160 plus $3.30 storage. A 50 GB namespace makes the same million queries about $800. Pinecone cost per query grows with corpus size; pgvector cost per query falls with query volume on a fixed box. That crossover, not raw latency, is the decision.

What the vendor benchmarks measured

Two published head-to-heads exist, both run by Postgres vendors, both against Pinecone’s older pod-based tier rather than serverless pricing. Read them as vendor benchmarks.

Supabase, October 2023: 1M dbpedia OpenAI embeddings at 1536 dimensions, inner product, pgvector v0.5.0 HNSW with m=36, ef_construction=128 on an 8-core, 32 GB instance (about $410/month) against roughly $480/month of Pinecone pods. Against s1 pods they report 1185% more QPS at accuracy@10 of 0.98 for Pinecone; against p2 pods, 0.95 vs 0.94 accuracy with pgvector faster.

Timescale, June 2024: 50M Cohere embeddings at 768 dimensions, PostgreSQL 16.3 with pgvector 0.7.0 and a pgvectorscale StreamingDiskANN index on an r6id.4xlarge (16 vCPU, 128 GB, $835/month), against 40 s1 pods ($3,241/month) and 32 p2 pods ($3,889/month). At 99% recall they report 28x lower p95 latency and 16x higher throughput than s1; at 90% recall, 1.4x lower p95 and 1.5x the throughput of p2, at 75% to 79% lower monthly cost.

There is no independent benchmark that includes Pinecone; ann-benchmarks covers open-source libraries only. Treat the numbers above as upper bounds set by parties with an interest.

Wiring it up

pgvector, with the settings that matter for an HNSW build and a filtered query:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE chunks (
  id        bigserial PRIMARY KEY,
  tenant_id int  NOT NULL,
  body      text NOT NULL,
  embedding vector(1536) NOT NULL
);

-- build fits in RAM => build is fast; 7 workers + leader
SET maintenance_work_mem = '8GB';
SET max_parallel_maintenance_workers = 7;

CREATE INDEX chunks_embedding_hnsw
  ON chunks USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

-- query side
SET hnsw.ef_search = 100;
SET hnsw.iterative_scan = relaxed_order;   -- pgvector >= 0.8.0
SET hnsw.max_scan_tuples = 20000;

SELECT id, body, embedding <=> $1 AS distance
FROM chunks
WHERE tenant_id = $2
ORDER BY embedding <=> $1
LIMIT 10;

Pinecone serverless, same shape:

from pinecone import Pinecone, ServerlessSpec

pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
pc.create_index(
    name="chunks",
    dimension=1536,
    metric="cosine",
    spec=ServerlessSpec(cloud="aws", region="us-east-1"),
)
idx = pc.Index("chunks")

idx.upsert(
    namespace=f"tenant-{tenant_id}",
    vectors=[{"id": "c1", "values": vec, "metadata": {"doc": "q3-report"}}],
)
res = idx.query(
    namespace=f"tenant-{tenant_id}",
    vector=qvec,
    top_k=10,
    filter={"doc": {"$eq": "q3-report"}},
    include_metadata=True,
)

Note the tenancy model: pgvector uses a column and the planner; Pinecone uses a namespace, which also bounds the RU cost of every query.

Filtering is where they diverge

pgvector applies WHERE after the index scan. The README gives the arithmetic: a predicate matching 10% of rows with ef_search at its default of 40 yields about 4 results on average. Since 0.8.0, hnsw.iterative_scan (strict_order or relaxed_order) keeps scanning until it has enough rows, bounded by hnsw.max_scan_tuples (default 20,000). For a handful of filter values, a partial index per value; for many, partition the table.

Pinecone describes its own approach as single-stage filtering: the metadata index is merged into the vector index, which it claims gives pre-filter accuracy without the brute-force cost. Operators are $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists, with $and/$or at the top level only, and at most 10,000 values in an $in per the metadata filter docs.

What you’ll see on the chart

pgvector, healthy: flat p99 with the index resident in shared buffers, recall stable when a filter is added. Unhealthy: a p99 cliff the day the index outgrows RAM and reads fall to disk; recall on filtered queries dropping toward zero for rare predicates until iterative scans are on; a slow build that means maintenance_work_mem was too small for the graph.

Pinecone, healthy: p99 steady across traffic spikes, fresh writes visible immediately because reads check the memtable first. Unhealthy: an RU line that climbs with namespace size even when QPS is flat; 429s when a single hot namespace crosses 100 requests per second; a bill that tracks corpus growth rather than usage.

Alert on recall against the golden set, not on latency alone. The measurement discipline is the same one described in SentryML’s monitoring metrics taxonomy.

Decision rule

Choose pgvector when the data already lives in Postgres, the corpus fits in the RAM of a box the team is willing to run, and joins or transactions against the vectors matter. Choose Pinecone when there is nobody to page for a database, tenancy runs to thousands of namespaces, traffic is spiky, and paying per read is preferable to paying for idle RAM. Between roughly a few million and fifty million vectors both work; the RU arithmetic above and the index memory footprint are what settle it.

Caveats

  • Both benchmarks cited are vendor benchmarks against pod-based Pinecone. Serverless pricing changes the cost side; re-run the arithmetic with RUs.
  • Recall must be measured against exact search on production queries. Filtered recall in pgvector below 0.8.0 fails silently.
  • pgvector indexes cap at 2,000 dimensions for vector and 4,000 for halfvec; a 3,072-dimension embedding needs halfvec or truncation.
  • Pinecone’s per-namespace 100 rps cap is a hard limit on hot tenants, not a soft quota.
  • Retrieval stores are an injection surface: content the index returns is model input. See AI Sec on indirect injection in RAG pipelines.

Sources

  1. pgvector README: index types, parameters, dimension limits, filtering and iterative scans
  2. Pinecone docs: serverless architecture
  3. Pinecone docs: understanding cost (read units and write units)
  4. Pinecone docs: database limits
  5. Pinecone pricing
  6. Pinecone: vector search filtering (pre, post and single-stage)
  7. Supabase: pgvector vs Pinecone benchmark (vendor, October 2023)
  8. Timescale (now TigerData): pgvector vs Pinecone benchmark with pgvectorscale (vendor, June 2024)
  9. pgvectorscale: StreamingDiskANN index for PostgreSQL
  10. Malkov and Yashunin, Efficient and robust approximate nearest neighbor search using HNSW graphs (arXiv 1603.09320)
  11. Subramanya et al., DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node (NeurIPS 2019)
#pgvector #pinecone #vector-database #hnsw #postgresql#comparison

Related