@b4run/memory-pgvector
Use this whenCopy link to section: Use this when
Use this package when multiple B4.run application instances need shared long-term memory with Postgres and pgvector. Keep SQLite for local or single-instance use. Choose this backend when shared durability and vector retrieval are worth running Postgres.
Install and importCopy link to section: Install and import
npm install @b4run/memory-pgvector pgimport { pgvectorMemoryStore } from "@b4run/memory-pgvector"Compatibility and audienceCopy link to section: Compatibility and audience
| Surface | Runtime | Purity | Audience | Stability |
|---|---|---|---|---|
@b4run/memory-pgvector | node-only | not-claimed | application | supported |
The store uses pg, initializes the pgvector extension and its tables lazily, and requires database credentials with the needed DDL and extension privileges.
Public exportsCopy link to section: Public exports
@b4run/memory-pgvectorCopy link to section: @b4run/memory-pgvector
| Export | Responsibility |
|---|---|
PgvectorMemoryStore | Extend MemoryStore with pool lifecycle. |
pgvectorMemoryStore | Create a Postgres and pgvector memory store. |
assertIdentifier | Reject unsafe SQL identifiers. |
IDENTIFIER_PATTERN | Expose the lowercase identifier pattern assertIdentifier enforces. |
initSchema | Initialize pgvector storage schema. |
vectorColumnDef | Select vector storage and operator class by dimensions. |
Key contractsCopy link to section: Key contracts
PgvectorMemoryStoreCopy link to section: PgvectorMemoryStore
export interface PgvectorMemoryStore extends MemoryStore {
close(): Promise<void>
}An injected pool remains caller-owned: close() is a no-op, and the caller owns pool error handling. A store-created pool receives an error listener and is ended by close().
export declare function pgvectorMemoryStore(opts: {
/** Postgres connection string; used to build an owned pool. */
connectionString?: string
/** An existing pool to use instead of building one from `connectionString`. */
pool?: Pool
/** Embedding dimensions (≤2000 → `vector`, ≤4000 → `halfvec`). */
dimensions: number
/** HNSW index/search tuning; all fields defaulted. */
index?: { m?: number; efConstruction?: number; efSearch?: number }
/** Postgres schema to place tables in; must match `IDENTIFIER_PATTERN`. */
schema?: string
/** Table name prefix (isolates multiple stores in one database); must match `IDENTIFIER_PATTERN`. */
tablePrefix?: string
/** Recall ranking tuning; all fields defaulted. See @b4run/memory score.ts. */
recall?: RecallRankingOptions
/** Store-level hybrid tuning; used when a query omits `vector`. All fields defaulted. */
vector?: VectorRankingOptions
}): PgvectorMemoryStoreBehavior contract memory-pgvector.schema.identifier-validation
pgvector schema and table-prefix identifiers reject unsafe characters before B4.run interpolates them into DDL.
Behavior contract memory-pgvector.dimension-branches
The store rejects invalid dimensions at construction: 1–2000 use vector cosine indexes, 2001–4000 use halfvec cosine indexes, and larger, nonpositive, or noninteger values throw.
Behavior contract memory-pgvector.update-preserves-embedding
update() preserves the row's stored embedding. Content or data updates do not recompute that embedding, so after changing semantic content, compute a replacement and call put(updatedRecord, { embedding, embeddingModel }) to avoid stale vector results.
Initialization and retrievalCopy link to section: Initialization and retrieval
Initialization is memoized per store instance. CREATE IF NOT EXISTS does not migrate an existing vector dimension or HNSW tuning, so treat those as schema decisions.
Both queryEmbedding and embedderId are required to activate hybrid retrieval. Keyword and vector candidates are fused in application code. schema and tablePrefix organize tables, but they are not tenant authorization boundaries. Both are interpolated unquoted, so both must be lowercase identifiers matching IDENTIFIER_PATTERN. A mixed-case value is rejected at construction rather than silently folded to lowercase by Postgres. Stored memory is plaintext unless your database and infrastructure provide encryption.
Examples and related guidesCopy link to section: Examples and related guides
import { pgvectorMemoryStore } from "@b4run/memory-pgvector"
const connectionString = process.env.DATABASE_URL
if (!connectionString) {
throw new Error("DATABASE_URL is required")
}
const store = pgvectorMemoryStore({
connectionString,
dimensions: 1536,
tablePrefix: "support_memory",
})
try {
await store.search({ namespace: "workspace=acme", query: "shipping" })
} finally {
await store.close()
}Continue with Long-term Memory, Recall and Retrieval, and Persistence and Tenancy.