LangChain4j Embedding Stores
Store and search vectors in LangChain4j: the in-memory store for tests, PgVector for production, Redis and Elasticsearch, plus metadata filtering and picking the right store.
On this page
The embedding store persists your vectors and answers similarity queries. LangChain4j abstracts over many stores behind one interface, so you can develop against an in-memory store and deploy against PgVector without changing your retrieval code. This tutorial covers the common stores and the metadata filtering that makes multi-tenant retrieval safe.
Key Takeaways
- InMemoryEmbeddingStore for tests; PgVector as the pragmatic production default.
- The store interface is uniform — swap implementations without touching retrieval code.
- Metadata filtering enforces tenant isolation; never rely on similarity alone for that.
- Adopt a dedicated vector database only when you have a concrete reason.
In-memory: for tests and prototypes
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
// Add and search — the same API every store implements.
store.add(embedding, segment);
EmbeddingSearchResult<TextSegment> result = store.search(EmbeddingSearchRequest.builder()
.queryEmbedding(queryVector)
.maxResults(5)
.minScore(0.7)
.build());Fast, zero setup, and lost on restart — exactly right for unit tests and prototypes, wrong for production.
PgVector: the production default
If you already run PostgreSQL, PgVector removes an entire piece of infrastructure:
EmbeddingStore<TextSegment> store = PgVectorEmbeddingStore.builder()
.host("localhost")
.port(5432)
.database("app")
.user("app")
.password(System.getenv("DB_PASSWORD"))
.table("embeddings")
.dimension(384) // MUST match your embedding model's output
.build();Other stores
EmbeddingStore<TextSegment> redis = RedisEmbeddingStore.builder()
.host("localhost").port(6379).dimension(384).build();EmbeddingStore<TextSegment> es = ElasticsearchEmbeddingStore.builder()
.serverUrl("http://localhost:9200").dimension(384).build();Qdrant, Milvus, Weaviate, Chroma, MongoDB Atlas, Neo4j and others each have a module. They all
implement the same EmbeddingStore interface, so your retrieval code is identical across them.
Metadata filtering
Filtering restricts the search before ranking — essential for multi-tenant systems and for narrowing by document version or date:
import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;
var result = store.search(EmbeddingSearchRequest.builder()
.queryEmbedding(queryVector)
.maxResults(5)
.minScore(0.7)
// Tenant isolation belongs in the filter, derived from the
// authenticated principal — never from a request parameter.
.filter(metadataKey("tenantId").isEqualTo(currentTenantId()))
.build());Filters compose:
var filter = metadataKey("tenantId").isEqualTo(tenantId)
.and(metadataKey("year").isGreaterThanOrEqualTo(2024));Choosing a store
| Store | Reach for it when | Watch out for |
|---|---|---|
| InMemory | Tests, prototypes | No persistence, no scale |
| PgVector | You already run Postgres | Index build time on huge tables |
| Redis | You run Redis, want low latency | Memory cost at scale |
| Elasticsearch | You need hybrid keyword + vector | Heavier to operate |
| Qdrant / Milvus | Hundreds of millions of vectors | Real distributed-systems overhead |
The honest advice, same as for Spring AI: start with PgVector. Most teams that adopted a dedicated vector database early would have been fine without one and carry the operational cost anyway.
Making ingestion idempotent
Re-ingesting must replace, not duplicate:
// Remove a source's existing vectors before re-adding, keyed on metadata.
store.removeAll(metadataKey("sourceId").isEqualTo(sourceId));
ingestor.ingest(freshDocuments);Next
- LangChain4j retrievers and RAG — turning this store into answers
- Vector databases deep dive — how the indexes work
- AI caching strategies
Frequently Asked Questions
Which embedding store should I use in LangChain4j?
How do I filter vector search by metadata in LangChain4j?
Is the in-memory store usable in production?
Do I need a dedicated vector database?
Related tutorials
- LangChain4j Embedding ModelsConfigure embedding models in LangChain4j: hosted models like OpenAI and Cohere, free in-process ONNX models, dimension matching, and choosing an embedding model for RAG.
- LangChain4j Retrievers & RAGBuild RAG in LangChain4j with ContentRetriever: attach retrieval to AI Services, transform queries, re-rank results, and assemble an advanced RAG pipeline with the RetrievalAugmentor.
- LangChain4j Text SplittersChunk documents effectively in LangChain4j: the recursive splitter, chunk size and overlap tuning, splitting code and markdown, and why chunking is the highest-impact decision in RAG.
- LangChain4j Agents & ToolsBuild tool-using agents in LangChain4j: the @Tool annotation, how the agent loop works, bounding iterations, safe write tools and the ReAct pattern — with production-ready code.