Overview
SKU Semantic Search uses PostgreSQL with the pgvector extension to store and search product embeddings. This setup enables efficient vector similarity search using SQL queries.Why PostgreSQL + pgvector?
Unified storage
Store both relational data (products, users) and vectors in one database. No separate vector database needed.
ACID compliance
Full transactional support ensures data consistency across product updates and searches.
SQL interface
Use familiar SQL syntax with SQLAlchemy ORM. No need to learn new query languages.
Cost-effective
No additional infrastructure or licensing costs. Works with standard PostgreSQL.
Docker setup (recommended)
The easiest way to get PostgreSQL with pgvector is using the official Docker image.Docker Compose configuration
The project includes a complete Docker Compose setup (docker-compose.yml:18):
- Image:
pgvector/pgvector:pg16- PostgreSQL 16 with pgvector pre-installed - Port mapping:
5435:5432- External port 5435 avoids conflicts with local PostgreSQL - Persistent storage:
postgres_datavolume preserves data across container restarts - Health check: Ensures database is ready before starting dependent services
Start the database
Manual PostgreSQL setup
If you prefer to use an existing PostgreSQL installation:- Ubuntu/Debian
- macOS
- Windows
Database initialization
The application automatically creates tables and enables the pgvector extension on startup (app/main.py:8):
- Connects to PostgreSQL using
DATABASE_URLfrom.env - Creates the
vectorextension if not already present - Creates all tables defined by SQLAlchemy models
The
IF NOT EXISTS clause makes this operation idempotent - safe to run multiple times.Product model and schema
Products are stored with their embeddings in theproducts table (app/models/product.py:5):
id: Auto-incrementing primary keyname: Product name, indexed for fast lookupsdescription: Full product descriptioncategory: Product category, indexed for filteringembedding: 3072-dimensional vector from Gemini’s embedding model
Generated SQL
SQLAlchemy creates this SQL:Vector operations
Creating embeddings
When a product is added, its embedding is generated and stored (app/services/product_service.py:8):
Vector similarity search
Searching uses cosine distance to find similar products (app/services/product_service.py:26):
cosine_distance: Measures angular similarity (recommended for text)l2_distance: Euclidean distanceinner_product: Dot product (for normalized vectors)
Performance optimization
For large product catalogs, add vector indexes:IVFFlat index
Fast approximate search (recommended for 10,000+ products):lists: Number of clusters (rule of thumb:rows / 1000)- Trade accuracy for speed
- Requires
ANALYZEafter creation
HNSW index
Higher recall, more storage (recommended for < 1M products):m: Max connections per layer (higher = better recall, more memory)ef_construction: Build-time accuracy (higher = better index, slower builds)
When to use IVFFlat vs HNSW
When to use IVFFlat vs HNSW
IVFFlat:
- Faster builds (good for frequently changing catalogs)
- Lower memory usage
- Slightly lower recall
- Best for 10K - 10M vectors
- Higher recall (more accurate results)
- Faster queries
- More memory intensive
- Best for < 1M vectors with stable catalogs
Index rebuild frequency
Index rebuild frequency
IVFFlat: Rebuild when:
- Product count changes by >20%
- Search quality degrades
- Run:
REINDEX INDEX index_name;
- Adding bulk products (>50% growth)
- Major catalog changes
Database maintenance
Backup and restore
Monitoring
Vacuum and analyze
Connection pooling
SQLAlchemy handles connection pooling automatically (app/db/session.py:6):
Troubleshooting
pgvector extension not found
pgvector extension not found
Error:
extension "vector" does not existSolution:- Verify you’re using the pgvector Docker image:
pgvector/pgvector:pg16 - For manual installations, check pgvector is installed:
SELECT * FROM pg_available_extensions WHERE name = 'vector'; - Ensure database user has
CREATEprivilege:GRANT CREATE ON DATABASE retail_rag TO postgres;
Connection refused
Connection refused
Error:
psycopg2.OperationalError: could not connect to serverSolution:- Check PostgreSQL is running:
docker ps - Verify port in
DATABASE_URLmatches Docker config (5435 for external) - For Docker API, use service name
dbas host, notlocalhost - Check firewall rules allow connections to port 5435
Slow vector searches
Slow vector searches
Symptoms: Queries take >1 second with 10,000+ productsSolution:
- Create a vector index (IVFFlat or HNSW)
- Run
ANALYZE products;to update statistics - Increase
work_memfor better sort performance: - Consider sharding if you have millions of products
Dimension mismatch error
Dimension mismatch error
Error:
dimension of vector must matchCause: Embedding dimension doesn’t match model definitionSolution:- Ensure all embeddings use the same model (Gemini: 3072 dimensions)
- If changing models, recreate embeddings:
- Re-run seed script to regenerate embeddings
Next steps
Environment setup
Configure DATABASE_URL and other environment variables
Docker deployment
Deploy the complete stack with Docker Compose
Architecture overview
Understand how the database fits into the system
RAG pattern
Learn how vector search powers RAG