Vector Store Backends
Semantic search via VectorStoreProtocol. Vector store backends store embedding vectors and perform similarity search, enabling meaning-based retrieval for memory, context, and knowledge systems. They are the engine behind Soothe’s “find by meaning, not keywords” capabilities.
What Vector Store Backends Do
Vector store backends manage collections of embedding vectors with associated metadata payloads. The core operations:
create_collection()— Initialize a vector table with a given dimension and distance metric.insert()— Add vectors with optional payloads (metadata dicts) and IDs.search()— Find nearest neighbors to a query vector, returning rankedVectorRecordresults with similarity scores.get/update/delete— CRUD operations on individual records by ID.list_records()— List records with optional metadata filters.reset()/delete_collection()— Clear data.
Critical design choice: All backends use self-provided vectors — Soothe generates embeddings externally (via its configured embedding model) and passes raw vectors to the store. No backend runs its own vectorizer. This ensures consistent embedding dimensions across backends.
Backend Comparison
| Feature | PGVectorStore | SQLiteVecStore | WeaviateVectorStore |
|---|---|---|---|
| Engine | PostgreSQL + pgvector | sqlite-vec extension | Weaviate v4 (gRPC) |
| Index type | HNSW / IVFFlat / none | HNSW (built-in) | HNSW (built-in) |
| Connection pooling | ✅ (psycopg_pool, default 5) | ✅ (reader pool, default 8) | ✅ (via client) |
| Metadata filtering | ✅ (SQL WHERE) | ⚠️ Limited | ✅ (GraphQL filters) |
| Concurrent writes | ✅ | ❌ (single writer, WAL) | ✅ |
| Cloud-ready | ✅ | ❌ (local file) | ✅ (Weaviate Cloud) |
| External dependencies | PostgreSQL, pgvector, psycopg_pool | sqlite-vec (optional, has fallback) | weaviate-client, Weaviate server |
| Setup complexity | Medium | Low | Medium-High |
| Scalability | High | Limited | High |
| Fallback behavior | N/A | Python-side similarity if extension missing | N/A |
Available Backends
PGVectorStore
Production-grade vector storage using PostgreSQL with the pgvector extension.
Key characteristics:
- Index choice: Supports HNSW (fast approximate search, higher recall, moderate build time), IVFFlat (faster build, good for large datasets), or no index (exact search, for small datasets <1000 vectors).
- Connection pooling via
psycopg_pool.AsyncConnectionPool(default 5 connections, min 1). - Distance metrics: cosine (default), l2 (Euclidean), ip (inner product) — mapped to pgvector operators.
- Metadata filtering via SQL WHERE clauses on JSONB payload columns.
- Native PostgreSQL integration — shares infrastructure with durability and persistence backends.
When to choose: Production deployments with existing PostgreSQL infrastructure, scenarios requiring scalable concurrent access, or when you want vector storage co-located with other Soothe data.
Minimal config:
vector_store:
enabled: true
provider: pgvector
dsn: postgresql://localhost/soothe
collection: soothe_vectors
vector_size: 1536
index_type: hnsw
Source: packages/soothe/src/soothe/backends/vector_store/pgvector.py
SQLiteVecStore
Embedded vector storage using the sqlite-vec extension — no external database required.
Key characteristics:
- Embedded: Vectors stored in a local SQLite database file (default
$SOOTHE_HOME/vector.db). Zero external dependencies. - Graceful fallback: If the sqlite-vec extension (virtual tables) is unavailable, falls back to Python-side similarity computation (
_cosine_similarity,_l2_distance,_ip_similarity). This is slower but functional. - WAL mode + reader pool: Concurrent reads via a reader pool (default 8 connections), single serialized writer via
asyncio.Lock. Supports multiple concurrent loops. - Binary vector packing: Vectors are packed into F32 binary format (
struct.pack) for efficient sqlite-vec storage. - Distance metrics: cosine, l2, ip — mapped to sqlite-vec distance functions.
When to choose: Local development, embedded deployments, single-process production, or any scenario avoiding external dependencies. The fallback ensures it works even without the extension installed.
Minimal config:
vector_store:
enabled: true
provider: sqlite_vec
db_path: ~/.soothe/vector_store/vector.db
collection: soothe_vectors
vector_size: 1536
Source: packages/soothe/src/soothe/backends/vector_store/sqlite_vec.py
WeaviateVectorStore
Cloud-native vector storage using Weaviate v4’s async client with gRPC.
Key characteristics:
- Self-provided vectors: Uses
skipvectorizer mode — Weaviate doesn’t generate embeddings; Soothe provides them. This ensures consistent embedding dimensions. - gRPC for search: Uses gRPC (default port 50051) for fast query/response, REST for management operations.
- Weaviate Cloud support: API key authentication for Weaviate Cloud deployments; local mode for self-hosted instances.
- Schema management: Automatic schema inference and collection creation.
- Timeout configuration: Init 30s, query 30s, insert 120s (configurable via
AdditionalConfig).
When to choose: Cloud-native deployments, managed vector search, multi-modal data, or when you need Weaviate’s GraphQL querying and module ecosystem (text2vec, img2vec, etc.).
Minimal config:
vector_store:
enabled: true
provider: weaviate
url: http://localhost:8080
grpc_port: 50051
collection: SootheVectors
Source: packages/soothe/src/soothe/backends/vector_store/weaviate.py
Index Type Selection (PGVectorStore)
| Index Type | Build Speed | Search Speed | Recall | Best For |
|---|---|---|---|---|
| HNSW | Moderate (O(n log n)) | Fast | High | Production, accuracy-critical |
| IVFFlat | Fast (O(n)) | Moderate | Good | Large datasets, speed-critical |
| None | N/A | Slow | Perfect | Small datasets (<1000), exact search |
Recommendation: Use HNSW for most production workloads — it offers the best recall-to-speed trade-off. Switch to IVFFlat only if build time becomes a bottleneck on very large datasets. Use none only for testing or tiny collections.
Performance Characteristics
| Operation | PGVector | SQLiteVec | Weaviate |
|---|---|---|---|
create_collection() |
~50-100ms | ~5-10ms | ~100-200ms |
insert() |
~20-50ms | ~10-20ms | ~50-100ms |
search() |
~50-100ms | ~20-50ms | ~100-200ms |
get() |
~10-30ms | ~5-10ms | ~50-100ms |
delete() |
~20-50ms | ~10-20ms | ~50-100ms |
list_records() |
~50-200ms | ~50-100ms | ~100-300ms |
SQLiteVec is fastest for local operations (no network). PGVector adds network overhead but scales to concurrent access. Weaviate has the highest latency due to gRPC/REST overhead but offers cloud scalability.
Search latency scales with collection size: HNSW search is approximately O(log n); exact search (no index) is O(n). Monitor search latency as collections grow.
Production Gotchas
-
Vector dimension is fixed per collection: The
vector_size(default 1536 for OpenAI embeddings) is set at collection creation and cannot change. Switching embedding models requires creating a new collection and re-inserting all vectors. -
SQLiteVec fallback is slow: Without the sqlite-vec extension, Python-side similarity computation iterates all vectors — O(n) per search. Install the extension for production use. The fallback exists for compatibility, not performance.
-
SQLiteVec single-writer contention: Like other SQLite backends, writes are serialized via
asyncio.Lock. Under heavy concurrent insertion, throughput is limited. PGVector and Weaviate handle concurrent writes via pooling. -
Weaviate timeout tuning: Default timeouts (init 30s, query 30s, insert 120s) may need adjustment for large batch inserts or slow networks. Increase
inserttimeout for bulk loading. -
PGVector index build time: Creating an HNSW index on a large existing table can take minutes to hours. Build the index after bulk insertion, not before, to avoid re-indexing overhead during loads.
-
Metadata filter limitations: SQLiteVec has limited metadata filtering compared to PGVector (SQL WHERE) and Weaviate (GraphQL). If complex filtering is critical, prefer PGVector or Weaviate.
-
Collection naming: PGVector uses the collection name as a table name; Weaviate uses it as a class name; SQLiteVec uses it as a table prefix. Ensure names are valid identifiers across your chosen backend.
Integration with Memory
Memory backends (MemUMemory) use vector stores indirectly — MemU maintains its own embedding store for semantic recall. However, the VectorStoreProtocol is available for direct semantic search use cases, and the protocol abstraction means you can swap engines without changing application code.
Related Documentation
- VectorStoreProtocol & AsyncPersistStore — Protocol interface definitions
- Backends Overview — Backend layer introduction
- Memory Backends — Memory semantic search integration
- RFC-001 — Vector store protocol spec