---
title: "Decision: Supabase pgvector over Pinecone"
url: https://mdfy.app/frK9IDOy
updated: 2026-05-14T18:15:49.480Z
source: "mdfy.app"
---
# Decision: Supabase pgvector over Pinecone

> Logged 2026-03-08 after a 2-day evaluation. Status: locked.

## What we picked

`pgvector` + HNSW inside the existing Supabase Postgres instance. **Not** Pinecone, Weaviate, Chroma, or Turbopuffer.

## What we measured

I built two prototypes against the same 4,200-document corpus (my actual hub plus a synthetic test set):

| Backend | Build time | Read p99 | Cold-start p99 | $/month at our scale |
|---|---:|---:|---:|---:|
| pgvector + HNSW | 41s | 18ms | 22ms | $0 (incl. with Postgres) |
| Pinecone serverless | n/a | 11ms | 380ms | ~$32 |

The cold-start gap was the surprise. Pinecone serverless can spike past 300ms when an index hasn't been touched in a few minutes, which is exactly our access pattern (bursty, per-user). pgvector inside the warm Postgres pool is steady.

## The argument for choosing the cheaper, slower-at-the-best-case option

- **One vendor, one auth surface, one migration story.** Adding Pinecone means a second SDK, a second control plane, a second set of API keys to rotate, a second "what region does it run in" answer.
- **18ms p99 read is well inside our 100ms recall budget.** The reranker is the bottleneck, not the vector store.
- **Postgres lets us join.** Filter by `user_id`, `folder_id`, `is_draft = false`, and `created_at > $cutoff` in the same query that returns the cosine match. Pinecone metadata filtering exists but is its own DSL.

## Where this stops being the right call

At ~50K vectors per user, HNSW recall starts to degrade unless we tune `ef_search`. We're nowhere near that. When we cross 30K we revisit, but we project that as the H2 2027 problem — not this quarter's.

## What I won't reconsider

The "but Pinecone is the obvious vector DB" pressure. It's the obvious choice in slide decks. The numbers say otherwise for our specific shape.
