Pinecone's $50/month minimum killed hobby RAG. This Pinecone alternative walks you through migrating to pgvector with vec2pg, schema, code, and cost math.
Pinecone recently detonated a lot of hobby RAG projects with a single email. If your side project holds tens of thousands of chunks and gets a few hundred queries a day, you now owe Pinecone at least $50 a month on Standard, or $20 on Builder if you accept its caps. That's the wrong shape of bill for a weekend project. pgvector runs inside the Postgres you probably already have, and moving a small index across takes an afternoon.
This piece walks the exact migration path: why the pricing change matters, how to design the schema, how to bulk-load with vec2pg, which index to build, and how to wire it back into LangChain or LlamaIndex, with the gotchas that will bite you.
Why Pinecone's Pricing Change Killed Hobby RAG
The new $50 minimum on Standard (and the $20 Builder tier)
Pinecone's own docs now spell out a monthly minimum on every paid plan: $20/month flat on Builder, $50/month on Standard, and $500/month on Enterprise. Only Starter stays at $0, and Starter has always been the "kick the tires" tier, not a place to run production-adjacent workloads.
The change landed via a customer email titled "Important pricing update: minimum usage fee", effective the 1st of the month. The developer who first flagged it had been a happy Pinecone user precisely because the old model was serverless in the truest sense: sign up, get an API key, pay for what you use. If your app went quiet for a month, the bill went to near-zero. That's the model that made Pinecone the default for hobby RAG.
What the Pinecone $50 minimum means for a sub-1M-vector project
Under the new floor, actual usage on a small index might be pennies, but you pay $20 or $50 regardless. On Standard that's $600/year; on Builder, $240/year. One developer described exactly this trigger: porting a RAG side project off Pinecone not because anything was broken, but because paying for a separate database while Postgres sat idle stopped making sense.
For anything under a million vectors with modest query volume, the minimum is now the whole bill. That's the segment Pinecone effectively priced out, and it's why "Pinecone alternatives hobby project" is now a common search.
Why pgvector Is the Pinecone Alternative for Small-Scale RAG
One database, not two
pgvector is a Postgres extension. Your embeddings live in a column next to the row they describe: one connection pool, one backup, one place to reason about consistency. The Chatsy team cut vector database costs by 97% moving from Pinecone to pgvector. The second database simply disappears from the invoice.
At Powabase, every project gets a dedicated, isolated Postgres with pgvector available as a one-line CREATE EXTENSION, sitting right next to your relational tables. For the "unify the stack" tradeoff we work through in our broader comparison of unified backends and compose-your-own vector stacks, sub-1M RAG is the easiest call in the matrix.
The alternatives you can skip
Chroma Cloud, Qdrant Cloud, and Weaviate Cloud are real options, and for specific workloads they're excellent. But for a hobby RAG project the calculus is thin: you're still adding a second system. Chatsy landed the same way after evaluating Weaviate, Milvus, and Qdrant. Weaviate added operational complexity, Milvus was overbuilt for their scale, and the managed offerings had similar cost concerns. Chroma self-hosted works fine locally and then quietly becomes a thing you have to babysit.
If the only reason you're shopping for a pinecone alternative is that the minimum stings, don't trade it for a different second database. Fold vectors into the Postgres you already run.
pgvector vs Pinecone Cost Comparison for Sub-1M Vectors
| Scenario | Pinecone floor | pgvector on managed Postgres |
|---|---|---|
| Idle side project | $20/mo Builder or $50/mo Standard | ~$5/mo box, or $0 marginal if you already run PG |
| 40k vectors, few hundred queries/day | Full minimum applies | Well inside a $5–$25 tier |
| Annualized minimum | $240–$600/year | Extension itself is free |
| Bill when app goes quiet | Same as active | Drops to hosting cost |
pgvector itself is free. You only pay for the Postgres instance it runs on, not for the extension. Managed Postgres with pgvector enabled starts around $5/month on Selfhost.dev, and if you already run Postgres for your app, the marginal cost of adding an embedding vector(1536) column is essentially zero.
Powabase's pricing is pay-as-you-go, so an idle project doesn't accrue a floor charge. That's the pricing shape Pinecone used to have.
Before You Migrate: Provisioning Postgres and pgvector
Enabling the extension
On any Postgres 13+ with pgvector available, enabling it is one line:
CREATE EXTENSION IF NOT EXISTS vector;
On managed hosts that ship pgvector (Powabase, Supabase, RDS, Neon, and others), that's all it takes. If you're rolling your own, install postgresql-15-pgvector from apt first.
Pick a host based on backup posture and connection pooling. A $5 box with no backups costs more than a $25 box with PITR the first time you TRUNCATE the wrong table.
Schema mapping from Pinecone to pgvector
Schema mapping Pinecone to pgvector is almost verbatim. Pinecone gives you an ID, a dense vector, and a metadata JSON blob per record:
CREATE TABLE document_embeddings (
id TEXT PRIMARY KEY,
content TEXT NOT NULL,
metadata JSONB,
embedding vector(1536),
created_at TIMESTAMPTZ DEFAULT NOW()
);
The vector(1536) dimension has to match your embedding model exactly: 1536 for OpenAI's text-embedding-3-small. Confirm your model's dimension in its own docs before writing DDL; getting this wrong means re-embedding everything later.
Two decisions worth making up front. First, keep content (the raw chunk text) in the same row as the embedding. You'll almost always want to return it with the search hit, and joining at query time is unnecessary latency. Second, index the fields you filter on inside metadata with a GIN index, or promote hot filter fields to real columns.
Migrating Pinecone to pgvector in an Afternoon
The migration to pgvector breaks into four steps:
- Export vectors and metadata from Pinecone.
- Load into Postgres, either with the vec2pg CLI tool or a hand-rolled upsert loop.
- Build the pgvector HNSW index after the load, not before.
- Swap the client library (Pinecone → LangChain PGVector or LlamaIndex PGVectorStore) and verify.
Exporting from Pinecone
Pinecone's Python client exposes fetch and list. Paginate through your index IDs, fetch in batches of 1,000, and dump each batch to newline-delimited JSON with id, values, and metadata. For a 40k-vector index this takes a few minutes.
Keep the raw export files around until the migration is verified end-to-end. They're your rollback.
Loading with the vec2pg CLI tool
The fastest path is Supabase's vec2pg, a CLI utility for migrating records from vector database vendors into pgvector. Install with:
pip install vec2pg
Point it at a Pinecone index and a Postgres connection string, and it handles batching and type conversion. It supports Pinecone and Qdrant out of the box; if your source isn't covered, weigh in on the vendor support issue on the project's GitHub.
For an afternoon migration on a single index, this is the tool.
Upserting manually with ON CONFLICT
If you'd rather not add a dependency, or your export has custom shape, a manual loader is 30 lines of Python. Read the NDJSON, batch into INSERT ... ON CONFLICT (id) DO UPDATE statements of 500-1,000 rows each, and commit per batch. ON CONFLICT makes the loader idempotent: rerun after a failure and you won't get duplicates.
Two tips that save an hour. Turn off synchronous commit for the loader session (SET LOCAL synchronous_commit = off), since you're bulk-loading and any failure means "rerun from the last batch" anyway. And don't create the HNSW index until after the load. Building it against an empty table and then inserting is dramatically slower than loading first and indexing once.
Building the pgvector HNSW Index
HNSW vs IVFFlat
For sub-1M vectors, the answer is essentially always HNSW: better recall at a given latency, and it handles inserts gracefully. IVFFlat is faster to build and uses less memory, but requires training data and re-training as your distribution shifts. That matters at 100M vectors, not 40k.
The canonical setup for cosine distance:
CREATE INDEX chunks_embedding_hnsw
ON chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
That's the exact configuration from a real hobby migration. Match the operator class to your embedding: vector_cosine_ops for OpenAI-family embeddings, vector_l2_ops for models trained on Euclidean distance, vector_ip_ops for inner product.
Tuning ef_construction, ef_search, and maintenance_work_mem
Three knobs matter:
ef_construction(build-time): higher means slower builds and better recall.ef_search(query-time): controls how many candidates to explore per query. The default of 40 is balanced; pushing to 80 or 100 buys recall at the cost of latency.maintenance_work_mem: set to 1–2 GB before creating the HNSW index, then reset. Build times drop dramatically.
For serving, size shared_buffers to about 25% of RAM so hot index pages stay resident. That's the single biggest lever for query latency on a warm cache.
Wiring pgvector Into Your RAG Stack
pgvector with LangChain PGVector and LlamaIndex PGVectorStore
Both major frameworks ship first-class pgvector integrations. LangChain's PGVector class takes a connection string, a collection name, and an embeddings object, and looks almost identical to the Pinecone integration it replaces (usually a 10-line diff in your retriever code). LlamaIndex's PGVectorStore is the same story, with hnsw_kwargs exposed directly so you can set hnsw_m, hnsw_ef_construction, and hnsw_ef_search from Python.
If your app uses LangChain's PineconeVectorStore today, the migration is: swap the import, swap the constructor, point at your Postgres URL, and rerun.
Hybrid search: full-text plus vector
The one thing that's genuinely easier on pgvector than on Pinecone is hybrid search, combining lexical (BM25 / tsvector) with dense vector similarity. LlamaIndex exposes it directly: hybrid_search=True with text_search_config="english" on PGVectorStore.from_params() gets you a combined query out of the box.
On Powabase this is built into the platform. Our knowledge bases expose vector, BM25, hybrid, and tree retrieval methods with reranking, so you don't hand-roll the fusion logic. Bare pgvector plus tsvector doesn't give you reranking, but simple score fusion covers most side-project queries.
Migration Gotchas and When to Stay on Pinecone
The pitfalls worth knowing before you cut over:
- Dimension mismatch. If your Pinecone index used a 3072-dim model and you declare
vector(1536), inserts fail loudly. Good. What's worse is declaringvector(1536)and quietly re-embedding new content with a different model. All chunks in a knowledge base must use the same embedding model. Change models and you reindex everything. - Metadata filter syntax. Pinecone's filter DSL doesn't map 1:1 to SQL
WHEREon JSONB. Audit every filter your app uses before you cut over. - First-load index build time. On a cold box with default
maintenance_work_mem, building HNSW over a few hundred thousand vectors takes longer than you'd expect. Raise the memory setting beforeCREATE INDEX. - Connection pooling. Pinecone hides connection management entirely. Postgres does not. Put PgBouncer or your host's built-in pooler in front of the database before pointing production traffic at it.
When a dedicated vector database still wins
pgvector on a single Postgres box handles millions of vectors well, tens of millions with tuning, and starts to strain past that. The honest triggers for moving to a dedicated vector DB are scale past what one 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.
At that scale, the $50 Pinecone minimum stops being the issue. The reason to pick pgvector as your Pinecone alternative this weekend is the opposite case: a side project where the bill dwarfs the workload. If you already run Postgres, take Abrar Qasim's advice and install pgvector on a staging copy, dump 10,000 real rows in, and run one query. Under an hour, and you'll know. Then export the vectors, run vec2pg, build the HNSW index, swap the client library, and be done before dinner.