PG Vector Store
The PgVector class provides vector search using PostgreSQL with pgvector extension. It provides robust vector similarity search capabilities within your existing PostgreSQL database.
Constructor OptionsDirect link to Constructor Options
connectionString?:
host?:
port?:
database?:
user?:
password?:
ssl?:
schemaName?:
max?:
idleTimeoutMillis?:
pgPoolOptions?:
Constructor ExamplesDirect link to Constructor Examples
Connection StringDirect link to Connection String
import { PgVector } from "@mastra/pg";
const vectorStore = new PgVector({
connectionString: "postgresql://user:password@localhost:5432/mydb",
});
Host/Port/Database ConfigurationDirect link to Host/Port/Database Configuration
const vectorStore = new PgVector({
host: "localhost",
port: 5432,
database: "mydb",
user: "postgres",
password: "password",
});
Advanced ConfigurationDirect link to Advanced Configuration
const vectorStore = new PgVector({
connectionString: "postgresql://user:password@localhost:5432/mydb",
schemaName: "custom_schema",
max: 30,
idleTimeoutMillis: 60000,
pgPoolOptions: {
connectionTimeoutMillis: 5000,
allowExitOnIdle: true,
},
});
MethodsDirect link to Methods
createIndex()Direct link to createIndex()
indexName:
dimension:
metric?:
indexConfig?:
buildIndex?:
IndexConfigDirect link to IndexConfig
type:
flat:
ivfflat:
hnsw:
ivf?:
lists?:
hnsw?:
m?:
efConstruction?:
Memory RequirementsDirect link to Memory Requirements
HNSW indexes require significant shared memory during construction. For 100K vectors:
- Small dimensions (64d): ~60MB with default settings
- Medium dimensions (256d): ~180MB with default settings
- Large dimensions (384d+): ~250MB+ with default settings
Higher M values or efConstruction values will increase memory requirements significantly. Adjust your system's shared memory limits if needed.
upsert()Direct link to upsert()
indexName:
vectors:
metadata?:
ids?:
query()Direct link to query()
indexName:
vector:
topK?:
filter?:
includeVector?:
minScore?:
options?:
ef?:
probes?:
listIndexes()Direct link to listIndexes()
Returns an array of index names as strings.
describeIndex()Direct link to describeIndex()
indexName:
Returns:
interface PGIndexStats {
dimension: number;
count: number;
metric: "cosine" | "euclidean" | "dotproduct";
type: "flat" | "hnsw" | "ivfflat";
config: {
m?: number;
efConstruction?: number;
lists?: number;
probes?: number;
};
}
deleteIndex()Direct link to deleteIndex()
indexName:
updateVector()Direct link to updateVector()
indexName:
id:
update:
vector?:
metadata?:
Updates an existing vector by ID. At least one of vector or metadata must be provided.
// Update just the vector
await pgVector.updateVector({
indexName: "my_vectors",
id: "vector123",
update: {
vector: [0.1, 0.2, 0.3],
},
});
// Update just the metadata
await pgVector.updateVector({
indexName: "my_vectors",
id: "vector123",
update: {
metadata: { label: "updated" },
},
});
// Update both vector and metadata
await pgVector.updateVector({
indexName: "my_vectors",
id: "vector123",
update: {
vector: [0.1, 0.2, 0.3],
metadata: { label: "updated" },
},
});
deleteVector()Direct link to deleteVector()
indexName:
id:
Deletes a single vector by ID from the specified index.
await pgVector.deleteVector({ indexName: "my_vectors", id: "vector123" });
disconnect()Direct link to disconnect()
Closes the database connection pool. Should be called when done using the store.
buildIndex()Direct link to buildIndex()
indexName:
metric?:
indexConfig:
Builds or rebuilds an index with specified metric and configuration. Will drop any existing index before creating the new one.
// Define HNSW index
await pgVector.buildIndex("my_vectors", "cosine", {
type: "hnsw",
hnsw: {
m: 8,
efConstruction: 32,
},
});
// Define IVF index
await pgVector.buildIndex("my_vectors", "cosine", {
type: "ivfflat",
ivf: {
lists: 100,
},
});
// Define flat index
await pgVector.buildIndex("my_vectors", "cosine", {
type: "flat",
});
Response TypesDirect link to Response Types
Query results are returned in this format:
interface QueryResult {
id: string;
score: number;
metadata: Record<string, any>;
vector?: number[]; // Only included if includeVector is true
}
Error HandlingDirect link to Error Handling
The store throws typed errors that can be caught:
try {
await store.query({
indexName: "index_name",
queryVector: queryVector,
});
} catch (error) {
if (error instanceof VectorStoreError) {
console.log(error.code); // 'connection_failed' | 'invalid_dimension' | etc
console.log(error.details); // Additional error context
}
}
Index Configuration GuideDirect link to Index Configuration Guide
Performance OptimizationDirect link to Performance Optimization
IVFFlat TuningDirect link to IVFFlat Tuning
- lists parameter: Set to
sqrt(n) * 2where n is the number of vectors - More lists = better accuracy but slower build time
- Fewer lists = faster build but potentially lower accuracy
HNSW TuningDirect link to HNSW Tuning
- m parameter:
- 8-16: Moderate accuracy, lower memory
- 16-32: High accuracy, moderate memory
- 32-64: Very high accuracy, high memory
- efConstruction:
- 32-64: Fast build, good quality
- 64-128: Slower build, better quality
- 128-256: Slowest build, best quality
Index Recreation BehaviorDirect link to Index Recreation Behavior
The system automatically detects configuration changes and only rebuilds indexes when necessary:
- Same configuration: Index is kept (no recreation)
- Changed configuration: Index is dropped and rebuilt
- This prevents the performance issues from unnecessary index recreations
Best PracticesDirect link to Best Practices
- Regularly evaluate your index configuration to ensure optimal performance.
- Adjust parameters like
listsandmbased on dataset size and query requirements. - Monitor index performance using
describeIndex()to track usage - Rebuild indexes periodically to maintain efficiency, especially after significant data changes
Direct Pool AccessDirect link to Direct Pool Access
The PgVector class exposes its underlying PostgreSQL connection pool as a public field:
pgVector.pool; // instance of pg.Pool
This enables advanced usage such as running direct SQL queries, managing transactions, or monitoring pool state. When using the pool directly:
- You are responsible for releasing clients (
client.release()) after use. - The pool remains accessible after calling
disconnect(), but new queries will fail. - Direct access bypasses any validation or transaction logic provided by PgVector methods.
This design supports advanced use cases but requires careful resource management by the user.