Integrating PGVector with Spring AI: Complete Practical Guide
PGVector is one of the most useful vector database options for Java and Spring AI applications because it brings vector search directly into PostgreSQL. If your application already uses PostgreSQL, PGVector allows you to store embeddings, run semantic similarity search, and build Retrieval-Augmented Generation systems without introducing a completely separate vector database.
Spring AI provides a PGVector VectorStore integration for storing document embeddings and performing similarity searches. PGVector itself is a PostgreSQL extension that supports storing and searching machine-learning-generated embeddings and can perform exact or approximate nearest-neighbor search. ([docs.spring.io](https://docs.spring.io/spring-ai/reference/api/vectordbs/pgvector.html?utm_source=chatgpt.com))
What is PGVector?
PGVector is an open-source PostgreSQL extension that adds vector data type support to PostgreSQL.
With PGVector, PostgreSQL can store vectors like:
[0.12, -0.45, 0.88, 0.31, -0.09, ...]
These vectors usually represent the meaning of text, documents, questions, products, tickets, policies, or knowledge base content.
Why Use PGVector with Spring AI?
PGVector is a strong option when you want semantic search and RAG inside a familiar PostgreSQL environment.
- Uses PostgreSQL infrastructure
- Works well with Spring Boot
- Supports semantic search
- Supports RAG workflows
- Can store metadata with embeddings
- Good for small to medium enterprise AI systems
- Reduces need for a separate vector database
Spring AI + PGVector Architecture
User Question
|
v
Spring Boot API
|
v
Embedding Model
|
v
PGVector VectorStore
|
v
Similar Documents Retrieved
|
v
ChatClient
|
v
Grounded AI Answer
Real-Time Example: Learning Platform
Suppose your learning website contains courses, interview questions, tutorials, and project explanations.
User searches:
I want to learn scalable Java backend deployment.
Keyword search may miss related content. PGVector semantic search can retrieve:
- Spring Boot Microservices
- Docker Deployment
- Kubernetes Autoscaling
- CI/CD with Kubernetes
- Cloud Deployment with AWS
This improves content discovery and user experience.
Real-Time Banking Example
A banking support AI assistant may store FAQs and policies in PGVector.
User asks:
Amount debited but UPI payment failed. What should I do?
PGVector can retrieve relevant policy documents about failed UPI transaction reversal even if the user does not use the exact policy wording.
Real-Time E-Commerce Example
An e-commerce AI assistant may store refund policy, delivery policy, warranty rules, and product descriptions.
User asks:
Can I return a damaged phone after delivery?
PGVector can retrieve semantically relevant return policy chunks and help the AI generate a grounded answer.
Step 1: Start PostgreSQL with PGVector Using Docker
The easiest setup is using the official PGVector Docker image.
docker run --name pgvector-db \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=spring_ai \
-p 5432:5432 \
-d pgvector/pgvector:pg16
Step 2: Enable PGVector Extension
Connect to PostgreSQL:
docker exec -it pgvector-db psql -U postgres -d spring_ai
Enable extension:
CREATE EXTENSION IF NOT EXISTS vector;
Check extension:
\dx
Step 3: Create Spring Boot Project
Create a Spring Boot project with:
- Java 17 or later
- Spring Web
- Spring JDBC
- PostgreSQL Driver
- Spring AI OpenAI or Ollama starter
- Spring AI PGVector Vector Store starter
Step 4: Add Spring AI BOM
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Step 5: Add Maven Dependencies
PGVector Vector Store Starter
Spring AI provides a PGVector vector store starter artifact named spring-ai-starter-vector-store-pgvector. ([central.sonatype.com](https://central.sonatype.com/artifact/org.springframework.ai/spring-ai-starter-vector-store-pgvector?utm_source=chatgpt.com))
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>
PostgreSQL Driver
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
OpenAI Starter Example
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
Step 6: Configure application.properties
spring.application.name=spring-ai-pgvector-demo
spring.datasource.url=jdbc:postgresql://localhost:5432/spring_ai
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.ai.model.embedding=openai
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.embedding.options.model=text-embedding-3-small
spring.ai.vectorstore.pgvector.initialize-schema=true
spring.ai.vectorstore.pgvector.index-type=HNSW
spring.ai.vectorstore.pgvector.distance-type=COSINE_DISTANCE
spring.ai.vectorstore.pgvector.dimensions=1536
The embedding dimension must match the embedding model. For example, if your embedding model produces 1536-dimensional vectors, PGVector must be configured with the same dimension.
Step 7: Understand PGVector Table Structure
Spring AI can initialize the vector store schema automatically when enabled.
Conceptually, a vector table stores:
- Document ID
- Text content
- Metadata
- Embedding vector
vector_store
|
+-- id
+-- content
+-- metadata
+-- embedding
Step 8: Create Document Ingestion Service
package com.dhanish.pgvector.service;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class KnowledgeIngestionService {
private final VectorStore vectorStore;
public KnowledgeIngestionService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
}
public void addSampleDocuments() {
Document springAiDoc = new Document(
"Spring AI helps Java developers build AI applications using chat models, embeddings, vector stores, and RAG.",
Map.of(
"topic", "spring-ai",
"source", "internal-course"
)
);
Document pgVectorDoc = new Document(
"PGVector is a PostgreSQL extension used to store and search vector embeddings for semantic search.",
Map.of(
"topic", "pgvector",
"source", "internal-course"
)
);
vectorStore.add(List.of(springAiDoc, pgVectorDoc));
}
}
Step 9: Create Semantic Search Service
package com.dhanish.pgvector.service;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SemanticSearchService {
private final VectorStore vectorStore;
public SemanticSearchService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
}
public List<Document> search(String query) {
return vectorStore.similaritySearch(query);
}
}
Step 10: Create Search Controller
package com.dhanish.pgvector.controller;
import com.dhanish.pgvector.service.KnowledgeIngestionService;
import com.dhanish.pgvector.service.SemanticSearchService;
import org.springframework.ai.document.Document;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/knowledge")
public class KnowledgeController {
private final KnowledgeIngestionService ingestionService;
private final SemanticSearchService searchService;
public KnowledgeController(KnowledgeIngestionService ingestionService,
SemanticSearchService searchService) {
this.ingestionService = ingestionService;
this.searchService = searchService;
}
@PostMapping("/load")
public String load() {
ingestionService.addSampleDocuments();
return "Documents added to PGVector successfully.";
}
@GetMapping("/search")
public List<Document> search(@RequestParam String query) {
return searchService.search(query);
}
}
Step 11: Test Document Ingestion
curl -X POST http://localhost:8080/api/knowledge/load
Expected Response
Documents added to PGVector successfully.
Step 12: Test Semantic Search
curl "http://localhost:8080/api/knowledge/search?query=How can Java developers build AI apps?"
Expected result should include the Spring AI document even if the query does not exactly match the stored text.
Semantic Search Flow
User Query
|
v
Embedding Generated
|
v
PGVector Similarity Search
|
v
Relevant Documents Returned
Step 13: Build RAG with PGVector and ChatClient
PGVector is most powerful when used with RAG.
User Question
|
v
Search PGVector
|
v
Retrieve Related Documents
|
v
Send Context to Chat Model
|
v
Generate Grounded Answer
RAG Answer Service Example
package com.dhanish.pgvector.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class RagAnswerService {
private final VectorStore vectorStore;
private final ChatClient chatClient;
public RagAnswerService(VectorStore vectorStore,
ChatClient.Builder builder) {
this.vectorStore = vectorStore;
this.chatClient = builder.build();
}
public String answer(String question) {
List<Document> documents =
vectorStore.similaritySearch(question);
String context = documents.stream()
.map(Document::getText)
.collect(Collectors.joining("\n\n"));
return chatClient.prompt()
.system("""
You are a helpful Spring AI assistant.
Use only the provided context.
If the answer is not available in the context,
say: I do not have enough information.
""")
.user("""
Context:
%s
Question:
%s
""".formatted(context, question))
.call()
.content();
}
}
RAG Controller Example
@RestController
@RequestMapping("/api/rag")
public class RagController {
private final RagAnswerService ragAnswerService;
public RagController(RagAnswerService ragAnswerService) {
this.ragAnswerService = ragAnswerService;
}
@GetMapping("/ask")
public String ask(@RequestParam String question) {
return ragAnswerService.answer(question);
}
}
Test RAG API
curl "http://localhost:8080/api/rag/ask?question=What is PGVector used for?"
Using PGVector with Ollama Embeddings
If you want local embeddings, you can use Ollama.
spring.ai.model.embedding=ollama
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.embedding.options.model=nomic-embed-text
spring.ai.vectorstore.pgvector.dimensions=768
Always confirm the embedding dimension of the model you use. If dimensions do not match the PGVector table, inserts may fail.
Using PGVector in Docker Compose
services:
postgres:
image: pgvector/pgvector:pg16
container_name: pgvector-db
environment:
POSTGRES_DB: spring_ai
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- pgvector-data:/var/lib/postgresql/data
volumes:
pgvector-data:
Spring Boot Docker Compose Connection
If Spring Boot runs on the host machine:
spring.datasource.url=jdbc:postgresql://localhost:5432/spring_ai
If Spring Boot runs inside the same Docker Compose network:
spring.datasource.url=jdbc:postgresql://postgres:5432/spring_ai
Index Types in PGVector
PGVector supports different search/indexing approaches. Spring AI PGVector supports configuration for index type and distance type. The Spring AI reference explains PGVector can identify exact and approximate nearest neighbors. ([docs.spring.io](https://docs.spring.io/spring-ai/reference/api/vectordbs/pgvector.html?utm_source=chatgpt.com))
| Index Type | Use Case |
|---|---|
| HNSW | Fast approximate nearest-neighbor search |
| IVFFlat | Approximate search with indexing |
| None | Small datasets or exact search |
Distance Types
| Distance Type | Meaning |
|---|---|
| Cosine Distance | Compares vector direction |
| Euclidean Distance | Compares geometric distance |
| Inner Product | Often used for similarity scoring |
Production Document Ingestion Pipeline
Document Uploaded
|
v
Validate File
|
v
Extract Text
|
v
Split into Chunks
|
v
Generate Embeddings
|
v
Store in PGVector
|
v
Ready for Semantic Search
Chunking Strategy
Do not store huge documents as one embedding. Split documents into meaningful chunks.
- Keep chunks focused
- Add metadata
- Use overlap for long explanations
- Avoid cutting important context
- Test retrieval quality
Metadata Strategy
Metadata helps with filtering, citations, debugging, and access control.
{
"source": "spring-ai-course",
"topic": "pgvector",
"module": "rag",
"tenantId": "dhanish-empower"
}
Multi-Tenant Search
If your application serves multiple users, companies, or customers, filter search results by tenant or user permission.
User A
|
v
Search only User A documents
User B
|
v
Search only User B documents
Without access filtering, one user may retrieve another user’s private documents.
Common Errors and Fixes
1. PGVector Extension Not Found
ERROR: type "vector" does not exist
Fix:
CREATE EXTENSION IF NOT EXISTS vector;
2. Dimension Mismatch
ERROR: expected 1536 dimensions, not 768
Fix:
- Check embedding model dimension
- Set
spring.ai.vectorstore.pgvector.dimensionscorrectly - Recreate table if dimension changed
3. Cannot Connect to PostgreSQL
Check:
- Database container is running
- Port mapping is correct
- Datasource URL is correct
- Username and password are correct
4. Empty Search Results
Possible causes:
- No documents added
- Poor chunking
- Wrong embedding model
- Similarity threshold too strict
- Metadata filter mismatch
5. Slow Search
Possible fixes:
- Add proper vector index
- Use HNSW or IVFFlat
- Reduce top-k
- Improve chunking
- Scale PostgreSQL resources
Performance Best Practices
- Use proper vector indexes
- Keep chunk size reasonable
- Use metadata filters
- Avoid very large top-k values
- Monitor query latency
- Use connection pooling
- Vacuum and maintain PostgreSQL regularly
- Separate OLTP workload and heavy vector workload if needed
Security Best Practices
- Protect PostgreSQL credentials
- Use environment variables or Kubernetes Secrets
- Enable database backups
- Use user-level or tenant-level metadata filtering
- Do not embed secrets unnecessarily
- Do not log sensitive documents
- Encrypt sensitive data where required
Monitoring PGVector-Based RAG
Track:
- Embedding generation time
- Vector search latency
- Top-k result quality
- Empty result count
- PostgreSQL CPU and memory
- Connection pool usage
- RAG answer fallback count
- User feedback score
Production Architecture
Frontend
|
v
Spring Boot AI API
|
+-- Document Ingestion Service
+-- Embedding Service
+-- PGVector VectorStore
+-- RAG Answer Service
+-- Monitoring Layer
|
v
PostgreSQL + PGVector
Best Practices Summary
- Use PGVector when PostgreSQL is already part of your stack
- Match embedding dimensions correctly
- Enable PGVector extension
- Use meaningful chunks
- Add metadata for filtering
- Use RAG prompts that avoid guessing
- Monitor vector search latency
- Secure tenant-specific retrieval
- Rebuild embeddings when changing embedding models
- Use indexes for larger datasets
Interview Questions
Q1: What is PGVector?
PGVector is a PostgreSQL extension that supports storing and searching vector embeddings for semantic search and AI applications.
Q2: Why use PGVector with Spring AI?
It allows Spring AI applications to store embeddings and perform semantic search using PostgreSQL.
Q3: What is VectorStore in Spring AI?
VectorStore is the Spring AI abstraction used to store and retrieve embeddings from vector databases such as PGVector.
Q4: Why does embedding dimension matter?
The vector table dimension must match the embedding model output dimension. Otherwise, insert or search operations may fail.
Q5: What is PGVector used for in RAG?
It retrieves semantically relevant documents that are added to the chat prompt for grounded AI responses.
Advanced Interview Questions
Q1: Difference between PostgreSQL full-text search and PGVector search?
Full-text search matches keywords, while PGVector search matches semantic meaning using embeddings.
Q2: Why use metadata with PGVector?
Metadata supports filtering, tenant isolation, source tracking, citations, and debugging.
Q3: What happens if you change embedding model?
You may need to regenerate all embeddings because vector dimensions and semantic spaces may change.
Q4: When should you not use PGVector?
For extremely large-scale vector workloads requiring specialized distributed vector infrastructure, a dedicated vector database may be better.
Q5: How do you secure PGVector retrieval?
Use authentication, authorization, tenant filters, safe metadata filters, secure database credentials, and avoid storing sensitive secrets as embeddings.
Recommended Learning Path
- Introduction to Spring AI
- Introduction to Embeddings
- Vector Databases and Vector Stores
- Integrating PGVector with Spring AI
- RAG with Java
- Prompt Engineering
- Java AI Agents
Summary
PGVector is a practical and powerful choice for Spring AI applications that need semantic search, embeddings, and RAG while continuing to use PostgreSQL.
Spring AI’s PGVector VectorStore integration makes it easier to add documents, generate embeddings, perform similarity search, and combine retrieved knowledge with ChatClient for grounded AI responses.
For learning platforms, banking assistants, e-commerce support systems, internal knowledge bases, and AI agents, PGVector provides a strong foundation for building production-ready semantic search and RAG features.