pgvector vs Pinecone: Do You Need a Vector Database?
For most apps, pgvector is enough and Pinecone is not needed: if your vectors fit comfortably in one Postgres database (up to several million is common) and you already run Postgres, keeping embeddings next to your data gives you joins, transactions and row-level permissions for free. Pinecone becomes the better choice when vector search is the product, when you have hundreds of millions of vectors, or when you want search capacity that scales without you sizing a database. This article compares pgvector and Pinecone on the things that decide the choice, and shows how to try the Postgres side in a few minutes.
#pgvector vs Pinecone in one table
| pgvector (in Postgres) | Pinecone | |
|---|---|---|
| What it is | An open-source Postgres extension (PostgreSQL License) | A managed vector database service |
| Where vectors live | In a column of your own tables | In Pinecone indexes, separate from your app data |
| Query language | SQL | Pinecone API and SDKs |
| Index types | HNSW, IVFFlat (approximate), or exact scan | Managed, no index tuning exposed |
| Filters | Any SQL WHERE, joins, Row Level Security | Flat JSON metadata filters ($eq, $in, $gt...) |
| Multi-tenancy | Rows with a tenant or user column plus RLS | Namespaces (one per customer is a common pattern) |
| Hybrid search | Combine with Postgres full-text search in SQL | Dense plus sparse indexes, built-in reranking |
| Embedding generation | You call a model (or use a platform feature) | Integrated hosted embedding models available |
| Free tier | Whatever your Postgres host gives you | Starter: 2 GB storage, 5 indexes, AWS us-east-1 only |
| Paid entry point | Your Postgres plan | Builder $20/month, Standard $50/month minimum (as of November 2026) |
Pinecone figures are from pinecone.io/pricing and the Pinecone docs, as of November 2026.
#What you give up by adding a second database
The case for pgvector is not that it beats Pinecone at vector search. It is that a second data store has costs that do not show up on the pricing page.
Two sources of truth. When a document is edited or deleted, the row in Postgres and the vector in Pinecone must change together. That means a sync job, a queue or a trigger that calls an API, and code to handle the case where one side succeeded and the other failed. With pgvector, the embedding is a column: one update or delete changes both, inside one transaction.
Permissions in two places. In a multi-user app, retrieval must only return chunks the current user may read. In Postgres, a Row Level Security policy on the chunks table does that for every query. In a separate vector store you replicate the rule yourself, usually as a metadata filter or a namespace per tenant, and you must never forget it in any code path. For RAG this matters a lot, because whatever retrieval returns ends up in a prompt.
Joins. "Find the 10 closest products that are in stock, cost under $50 and ship to Germany" is one SQL query when vectors and products share a database. With a separate store you either copy those fields into metadata (and keep them in sync) or fetch candidates and filter in your app.
One more bill, one more outage surface. Another service to monitor, another set of keys, another region to think about for data residency.
None of these are dealbreakers. Teams run Pinecone next to Postgres successfully every day. But if you do not need what Pinecone adds, you are paying these costs for nothing.
#What Pinecone does better
Be honest about where a dedicated service wins:
- Scale without sizing. You do not pick instance sizes, tune
maintenance_work_memor watch an HNSW build. Pinecone's serverless indexes handle storage and query capacity for you. - Very large collections. pgvector on a single Postgres server is bounded by that server's memory and disk. Pinecone is built for collections far larger than a typical app database.
- Built-in hybrid and reranking. Pinecone has sparse indexes for keyword-style relevance and hosted reranking models, so hybrid retrieval is configuration, not code.
- Integrated embeddings. You can send text and let Pinecone embed it with a hosted model, both at write and at query time.
- Isolation of load. Heavy vector queries never compete with your app's transactional queries for CPU, because they run elsewhere.
If two or more of these describe your situation, Pinecone, or another dedicated vector database, is a reasonable choice. See pgvector vs Qdrant vs Weaviate for the open-source dedicated options.
#Cost: a worked example
Take one million chunks embedded with a 1,536-dimension model.
pgvector. The pgvector docs give storage as 4 * dimensions + 8 bytes per vector, so 6,152 bytes each, about 6.2 GB for a million, before the text and the index. An HNSW index adds a significant amount on top; measure yours with select pg_size_pretty(pg_relation_size('chunks_embedding_idx')) rather than guessing. If you store halfvec instead (half precision, 2 * dimensions + 8 bytes), the raw vectors drop to about 3.1 GB; check recall on your own queries before you switch.
On StitchDB, the Pro plan ($15.99/month) includes a 10 GB database per project, and database size above that costs $0.12 per GB-month on Pro (as of November 2026; see pricing). A million half-precision vectors with their text and index can fit in or near that allowance; full-precision vectors with an HNSW index will likely go over it and pay the per-GB rate.
Pinecone. On Standard, storage is $0.33 per GB-month, writes are $4 to $4.50 per million write units and reads $16 to $18 per million read units, with a $50 monthly minimum (as of November 2026). The storage part of a million vectors is small; what drives the bill is the minimum and query volume.
The honest summary: at a million vectors, both are cheap, and the difference is mostly whether you want to pay a minimum for a second service. At hundreds of millions of vectors, the comparison changes, because a Postgres server big enough for that index is not a small plan.
#Performance: what to expect from pgvector
pgvector's HNSW index gives fast approximate search on millions of rows when the index fits in memory. Three settings matter most:
-- More candidates explored per query: better recall, slower (default 40)
set hnsw.ef_search = 100;
-- Filtered queries: keep scanning the index until enough rows pass the filter
-- (pgvector 0.8.0 and newer)
set hnsw.iterative_scan = relaxed_order;
-- Faster index builds, if the server has the memory
set maintenance_work_mem = '2GB';The second one fixes the classic complaint about filtered vector search in Postgres. Without it, filtering happens after the index returns its candidates, so a selective where can return fewer rows than your limit. Check your version with:
select extversion from pg_extension where extname = 'vector';If you want hard numbers for your workload, test on your own data. Vendor benchmarks, including ones published by vector database companies, use datasets and settings that may not match yours.
#A checklist: do you need a vector database?
You probably do not need one if:
- Your vectors are under a few million rows and grow at the pace of your app data.
- Retrieval must respect per-user or per-tenant permissions.
- Results must be filtered or joined with relational data (price, stock, dates, ownership).
- You want one backup, one restore point and one place to delete a user's data.
- Your team already knows SQL.
You probably do want one if:
- Vector search is the core product and query volume is high and spiky.
- You expect hundreds of millions of vectors or more.
- You want hosted embeddings, sparse indexes and reranking without building them.
- You do not want to size or tune a database at all.
#Trying the Postgres side on StitchDB
StitchDB gives each project its own Postgres database, and vector is one of the available extensions. In Studio open Database → Extensions, switch on vector, or run:
create extension if not exists vector with schema extensions;
create table public.chunks (
id bigint generated always as identity primary key,
user_id uuid not null default auth.uid() references auth.users on delete cascade,
content text not null,
embedding extensions.vector(1536) not null
);
alter table public.chunks enable row level security;
create policy "own chunks" on public.chunks
for select to authenticated using (user_id = auth.uid());
create index on public.chunks using hnsw (embedding extensions.vector_cosine_ops);Wrap the nearest-neighbor query in a function and call it from the client with RPC; the pgvector guide has the full match_chunks function and an Edge Function that creates embeddings. Because the function runs as the calling user, the policy above applies and each user only ever matches their own chunks.
If what you actually need is a search box that understands meaning, StitchDB also has a built-in search index that embeds rows for you and does hybrid keyword and semantic ranking with RLS applied. Semantic search there is included from the Pro plan up to a monthly number of embeddings (500,000 on Pro as of November 2026).
Trade-offs to know: StitchDB runs in EU data centers only (Germany and Finland), so if your users and services are all in the US, a US-hosted option may give lower latency. And like any single-database setup, a very large vector index competes with your app for the same server's memory; the Scale and Enterprise plans can move a project to a dedicated server when that becomes a problem.
#Moving from Pinecone to pgvector
If you already use Pinecone and want to consolidate:
- Create a table with the same dimension as your Pinecone index and columns for the metadata you filter on.
- Export vectors and metadata from Pinecone with its API (fetch or list by ID), and insert them in batches. Vectors are plain arrays of floats, so no re-embedding is needed if you keep the same model.
- Build the HNSW index after the bulk load; it is faster than indexing row by row.
- Run your real queries against both for a while and compare the top results.
- Switch reads, then writes, then delete the Pinecone index.
#FAQ
#Is pgvector as fast as Pinecone?
For a few million vectors with an HNSW index in memory, pgvector is fast enough for interactive search and RAG. At very large scale, a dedicated service is built to stay fast without you tuning it. Measure on your own data.
#Can pgvector handle 10 million vectors?
Yes, if the server has the memory and disk for the index. Use halfvec to halve storage, build the index with enough maintenance_work_mem, and watch database size against your plan.
#Does Pinecone have a free tier?
Yes. As of November 2026 the Starter plan is free with 2 GB of storage, up to 5 indexes, 2 million write units and 1 million read units a month, on AWS us-east-1 only.
#Can I keep using Pinecone with a Postgres backend?
Yes. Many apps store app data in Postgres and vectors in Pinecone. You then need a sync step on every insert, update and delete, and you must apply permissions in your retrieval code.
#Which distance should I use?
Cosine distance (<=> with vector_cosine_ops) is the safe default for text embeddings. Use the same distance your embedding model recommends.
Try vectors next to your data: enable vector under extensions and create a free project.