Why local RAG exists
A local RAG setup keeps every byte of data on the machine it lives on — no document, chunk, or query ever leaves your own hardware. For businesses with genuinely sensitive documents (legal, medical, financial), this removes an entire category of vendor-trust question that a cloud-hosted vector database always carries. (sitepoint.com)
Note
The actual pipeline
Ingest documents, chunk them into manageable segments, generate vector embeddings for each chunk, store those vectors in a database, then at query time embed the user's question and retrieve the most semantically similar chunks to ground the AI's answer in your actual files. (sitepoint.com)
The two decisions that matter most before you touch a database are chunking strategy and embedding model choice — the vector database itself is a smaller lever than most setup guides imply.
Chunking: the part everyone underrates
Recursive character splitting at 512 tokens with 50–100 tokens of overlap is the benchmark-validated default for most RAG applications, scoring 69% accuracy in the largest real-document test of 2026. Factoid queries work well at 256–512 tokens, while analytical and multi-hop queries benefit from 512–1,024 token chunks. (premai.io)
Chroma's own research found recursive splitting delivers 85–90% recall at 400 tokens, while semantic chunking (splitting on meaning boundaries rather than fixed character counts) reaches 91–92% and is considered the gold standard for production in 2026. But smaller isn't automatically better: in the FloTorch 2026 benchmark, semantic chunking that produced fragments averaging just 43 tokens scored only 54% accuracy end-to-end — too little context per chunk hurts as much as too much. A January 2026 systematic analysis also identified a "context cliff" around 2,500 tokens where response quality drops sharply. (firecrawl.dev)
Warning
Embedding models: the local options
You need a model that turns text into vectors, and running it locally (via sentence-transformers or Ollama) keeps the entire pipeline — not just storage — off the network.
| Model | MTEB score | Params | Context | License | Notes |
|---|---|---|---|---|---|
| Qwen3-Embedding-8B | 70.58 (multilingual) | 8B | 32,000 tokens | Apache 2.0 | Best open-source score, heaviest to run |
| BGE-M3 | 63.0 | 568M | 8,192 tokens | MIT | Dense + sparse + multi-vector from one model |
| Nomic Embed Text v1.5 | ~62 | 137M | 8,192 tokens | Apache 2.0 | Fully open weights/code/training data; runs via Ollama |
| all-MiniLM-L6-v2 | 56.3 | ~22M | 256 tokens | Apache 2.0 | Default sentence-transformers starting point, <10ms on CPU |
BGE-M3 or Nomic Embed v2 are recommended for laptop users with 8GB RAM — both run comfortably and support hybrid (dense + keyword) retrieval. Nomic-Embed-Text-v1.5 is the most CPU-friendly option in this set at roughly 1,400 tokens/sec on CPU, and it's available directly on Ollama for fully offline inference with no external API dependency. all-MiniLM-L6-v2 is fast but its MTEB score of 56.3 makes it uncompetitive with the others for production retrieval quality — fine for a quick prototype, not for something you're shipping. (premai.io, local-ai-zone.github.io)
As of April 2026, three open embedding models match or beat OpenAI's text-embedding-3-large on retrieval accuracy in actual RAG benchmarks while costing $0 per million tokens — the gap between "free and local" and "paid and hosted" has effectively closed for embeddings specifically, even where it hasn't for generation. (local-ai-zone.github.io)
Real local-capable vector databases
Qdrant runs locally, in Docker, on Kubernetes, or as managed cloud — genuinely flexible deployment, and specifically good for filter-heavy RAG (retrieving within one customer's data, a permission boundary, a date range) because it applies filters before the vector search rather than after, which is both faster and more accurate. Chroma is open-source, stores embeddings with metadata, and supports local development directly — the same API that runs in a Python notebook scales to a production cluster. ChromaDB and FAISS both use minimal RAM, reportedly a few hundred MB even for thousands of documents, so this isn't an infrastructure-heavy undertaking to start. (braintrust.dev, sitepoint.com, datacamp.com)
Beyond those two, LanceDB, pgvector, and FAISS round out the realistic local options, each with a different tradeoff:
| Database | Local memory footprint | Best for | Cost (self-hosted) | Notes |
|---|---|---|---|---|
| ChromaDB | 4–8 GB handles millions of embeddings | Prototyping through mid-scale production | Under $30/mo | Single VPS sufficient for 100K–few million chunks; in-process, no network latency |
| Qdrant | ~8 GB recommended | Complex filtering (legal, financial, multi-tenant) | $30–$50/mo | Rust-based, consistent latency |
| pgvector | Adequate under 2–3M vectors | Teams already running PostgreSQL | $0 incremental if DB exists | Needs tuning past a few million vectors |
| LanceDB | Disk-efficient, handles larger-than-memory datasets | Edge deployments, desktop apps, no-server workflows | Under $30/mo for moderate corpora | Superior batch ingestion/re-indexing |
| FAISS | A few hundred MB | Research, embedding into your own app | $0 (library, not a DB) | No persistence, replication, or multi-tenancy — it's a library, not a database |
The community recommendation in 2026 is consistent: Chroma for new RAG projects and prototypes, with a migration path to Qdrant (for filtering-heavy needs) or pgvector (if you already run Postgres and stay under roughly 10M vectors) once requirements grow past what a single lightweight instance handles. (4xxi.com)
How retrieval actually finds the right chunk: HNSW
Every one of these databases needs an indexing algorithm to avoid comparing a query vector against every stored vector one by one — that brute-force approach doesn't scale past a small corpus. The dominant answer in production systems is HNSW (Hierarchical Navigable Small World), an approximate nearest neighbor algorithm built on proximity graphs that connect each vector to a handful of others based on distance. (pyimagesearch.com)
HNSW organizes vectors into multiple layers. Search starts at the top layer, which has the fewest nodes, and the algorithm looks for a good entry point close to the query vector; it then descends through progressively denser layers, gathering a pool of candidate vectors that are close to the query at each level, until it reaches the bottom layer holding the full dataset. This layered approach means the algorithm skips most of the search space entirely rather than scanning everything, which is what makes it "approximate" — it trades a small amount of recall accuracy for a dramatic reduction in query time. For large-scale retrieval across thousands of documents, HNSW offers the best accuracy-latency balance of the widely available ANN approaches, which is why Chroma, Qdrant, Weaviate, and pgvector all use it (or a close variant) as their default index type. (pyimagesearch.com)
Practically, this matters for local setups because HNSW's memory footprint scales with the graph structure, not just the raw vectors — it's a meaningful chunk of why Qdrant recommends ~8GB RAM and Weaviate recommends 16GB even though the raw embedding data itself would fit in far less. If you're running on constrained hardware, this is the tuning knob (ef_construction, m, and similar parameters vary by database) worth understanding before you assume you need bigger hardware.
A minimal working example (Chroma)
This is the shape of a local pipeline end to end — ingest, embed, store, and query — using Chroma with a local sentence-transformers model. No API keys, no network calls beyond the initial model download.
import chromadb
from chromadb.utils import embedding_functions
# Local embedding model - runs entirely on your machine
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="BAAI/bge-m3"
)
# Persistent local client - data lives in ./chroma_db
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(
name="internal_docs",
embedding_function=embedding_fn,
)
# Ingest: chunk your documents upstream, then add them
collection.add(
documents=[
"Refund requests must be filed within 30 days of purchase.",
"Employee expense reports over $500 require manager approval.",
],
metadatas=[{"source": "policy.pdf", "page": 4}, {"source": "finance.pdf", "page": 2}],
ids=["chunk-1", "chunk-2"],
)
# Query: embed the question, retrieve the closest chunks
results = collection.query(
query_texts=["How long do I have to request a refund?"],
n_results=2,
)
print(results["documents"])
Swap SentenceTransformerEmbeddingFunction for an Ollama-backed Nomic Embed call and PersistentClient for QdrantClient if you need filtering — the pipeline shape stays identical; only the storage and embedding backends change.
What you're actually trading off
A local setup avoids cloud data exposure but means you're responsible for your own uptime, backups, and scaling — a cloud vector database handles that for you at the cost of your data living on someone else's infrastructure. For a small internal knowledge base, local is genuinely low-effort; for something that needs to scale to many concurrent users, the operational tradeoff shifts. Pinecone, for comparison, is fully managed with zero operational overhead but scales in cost from $70–$300+/month standard up to $500–$1,500/month at 5M+ vectors — the price of not thinking about any of this yourself. (4xxi.com)
Tip
The practical starting point
For a first local RAG setup: Chroma or a local Qdrant instance, paired with BGE-M3 or Nomic Embed running locally via sentence-transformers or Ollama, and recursive chunking at 400–512 tokens as a starting point (test semantic chunking once you have a baseline). This gets you a fully private document search pipeline without needing to understand vector database internals deeply first — the minimal-RAM footprint on the Chroma/FAISS side means this runs fine on ordinary hardware, not just a dedicated server. Move to Qdrant or pgvector only once you have a concrete reason: heavy metadata filtering, an existing Postgres instance, or a corpus crossing a few million chunks.
Sources: SitePoint — Local RAG Without the Cloud: Private Document AI Setup, Braintrust — Best Vector Databases for RAG in 2026, 4xxi — Vector Database Comparison 2026: ChromaDB vs. Qdrant vs. pgvector vs. Pinecone vs. LanceDB, DataCamp — Best Vector Databases 2026, PremAI — Best Embedding Models for RAG (2026), Local AI Zone — Top Embedding AI Models 2026, Firecrawl — Best Chunking Strategies for RAG (2026), PremAI — RAG Chunking Strategies: The 2026 Benchmark Guide, PyImageSearch — Vector Search with FAISS: Approximate Nearest Neighbor (ANN) Explained
Get new posts as they publish
No spam — just the next post, straight to your inbox.