Prompt
I'm building semantic search over product docs and need advice on storage and indexing
Latest observation
For semantic search over product docs, the main decision is usually where to store the source docs, embeddings, and metadata, and what to index for retrieval. A practical setup looks like this:
Recommended architecture
1) Store raw documents separately
Keep the original docs in durable object storage or a document store:
- S3 / GCS / Azure Blob
- PostgreSQL / MongoDB if docs are smaller and structured
- A search index should not be your only source of truth
Store:
- document ID
- title
- body / chunks
- version
- source URL
- access control info
- last updated timestamp
2) Chunk before embedding
Don’t embed whole docs unless they’re small. Chunk by:
- headings / sections
- paragraphs
- ~200–500 tokens per chunk as a starting point
Each chunk should carry metadata:
- doc_id
- chunk_id
- section title
- product/version
- language
- permissions/tags
3) Store embeddings in a vector index
Use a vector-capable database or search engine:
- pgvector if you want simplicity and already use Postgres
- Pinecone / Weaviate / Milvus / Qdrant for dedicated vector search
- Elasticsearch / OpenSearch if you want hybrid lexical + vector in one system
Index fields typically:
- chunk embedding
- chunk text
- metadata filters
- maybe sparse lexical fields for BM25
Indexing strategy
Best practice: hybrid retrieval
Semantic search works better when combined with keyword search:
- Vector search for meaning
- BM25/keyword search for exact terms, part numbers, error codes, product names
Typical flow:
- Query comes in
- Run vector similarity search
- Run lexical search
- Merge/rerank results
This is especially important for product docs because users often search for:
- exact feature names
- version numbers
- error codes
- acronyms
Use metadata filters
Index metadata so you can filter by:
- product line
- doc type
- language
- version
- access scope
This helps both relevance and security.
Consider reranking
If you need higher precision:
- retrieve top 20–100 candidates
- rerank with a cross-encoder or LLM reranker
- return top 5–10
Storage choices by scale
Small to medium scale
If you’re starting out:
- PostgreSQL + pgvector
- separate table for docs/chunks
- GIN/B-tree indexes on metadata
- full-text search in Postgres for lexical fallback
Good when:
- < a few million chunks
- you want simpler ops
- you need transactional consistency
Medium to large scale
If search performance is more important:
- OpenSearch/Elasticsearch for hybrid search
- or Qdrant/Weaviate/Milvus for vectors + separate keyword layer
Good when:
- many millions of chunks
- heavy query traffic
- multiple filters and facets
Practical schema example
Documents table
- doc_id
- source
- title
- url
- product
- version
- permissions
- updated_at
Chunks table
- chunk_id
- doc_id
- chunk_text
- chunk_order
- section_title
- embedding
- language
- metadata JSONB
Indexes:
- vector index on embedding
- B-tree on doc_id, product, version
- GIN on metadata JSONB if using Postgres
- full-text index on chunk_text for keyword search
Operational advice
Re-embed on content changes
Track document versions. When docs change:
- re-chunk if structure changed
- re-embed affected chunks
- delete old chunk vectors
Deduplicate
Product docs often repeat boilerplate. Remove or down-rank:
- navigation text
- legal disclaimers
- repeated headers/footers
Monitor retrieval quality
Track:
- click-through
- query success rate
- zero-result queries
- top query terms with poor recall
If you want the simplest solid stack
A good default is:
- PostgreSQL for doc/chunk storage
- pgvector for embeddings
- Postgres full-text search for lexical matching
- metadata filters in JSONB
- optional reranker later
This is usually enough to get a strong semantic search MVP without too much infrastructure.
If you tell me:
- your expected corpus size,
- update frequency,
- whether you need strict ACLs,
- and your preferred stack,
I can recommend a specific schema and indexing plan.