@b4run/postgres-storage
Use this whenCopy link to section: Use this when
Use this package when a deployed B4.run application needs shared durable checkpoints, Agent Protocol threads, and permission grants across instances. Each permissions-store instance caches grants and observes another instance's writes after its next load(). The root accepts a structural pool for Node or edge hosts. /node adds pg connection-string convenience.
Install and importCopy link to section: Install and import
npm install @b4run/postgres-storage pgimport { createPostgresThreadsStore } from "@b4run/postgres-storage"
import { postgresCheckpointer } from "@b4run/postgres-storage/node"Compatibility and audienceCopy link to section: Compatibility and audience
| Surface | Runtime | Purity | Audience | Stability |
|---|---|---|---|---|
@b4run/postgres-storage | edge-safe | not-claimed | application | supported |
@b4run/postgres-storage/node | node-only | not-claimed | application | supported |
The edge-safe classification covers the root's import graph. It is tested on local workerd with a Neon WebSocket pool, not on every edge provider or a live Cloudflare deployment.
Public exportsCopy link to section: Public exports
@b4run/postgres-storageCopy link to section: @b4run/postgres-storage
| Export | Responsibility |
|---|---|
PostgresCheckpointerOptions | Configure the checkpointer. |
B4PostgresSaver | Implement LangGraph checkpoint persistence. |
postgresCheckpointer | Create a Postgres checkpointer. |
PostgresStoreOptions | Configure shared connection and table naming. |
PostgresPermissionsStore | Define the durable permissions store. |
PostgresPermissionsStoreOptions | Configure permissions storage and policy. |
createPostgresPermissionsStore | Create a permissions store. |
assertIdentifier | Reject unsafe SQL identifiers. |
DEFAULT_SCHEMA | Expose the default schema. |
DEFAULT_TABLE_PREFIX | Expose the default table prefix. |
IDENTIFIER_PATTERN | Expose the lowercase identifier pattern assertIdentifier enforces. |
SqlClient | Define the structural SQL client. |
SqlPool | Define the structural SQL pool. |
SqlResult | Describe a structural query result. |
CreateThreadInput | Describe thread creation. |
PostgresThreadsStore | Define a durable threads store. |
PostgresThreadsStoreOptions | Configure thread storage. |
Thread | Describe an Agent Protocol thread. |
ThreadStatus | Name thread runtime status. |
ThreadsStore | Define the threads-store contract. |
createPostgresThreadsStore | Create a threads store. |
InterruptGrantRecord | Describe a stored approval-grant row. |
InterruptGrantStore | Define the approval-grant store contract. |
InterruptGrantConsumption | Describe a conditional consume's outcome. |
PostgresInterruptGrantStore | Define a durable approval-grant store. |
PostgresInterruptGrantStoreOptions | Configure approval-grant storage. |
createPostgresInterruptGrantStore | Create an approval-grant store. |
ClientToolCallRecord | Describe a stored client tool call row. |
ClientToolCallAnswer | Describe an answer attempt's outcome. |
ClientToolCallStore | Define the client tool call store contract. |
PostgresClientToolCallStore | Define a durable client tool call store. |
PostgresClientToolCallStoreOptions | Configure client tool call storage. |
createPostgresClientToolCallStore | Create a client tool call store. |
@b4run/postgres-storage/nodeCopy link to section: @b4run/postgres-storage/node
The /node entry also re-exports every root export. The rows below list them again. Its three factories use the connection-string-aware implementations.
| Export | Responsibility |
|---|---|
NodePostgresStoreOptions | Add connection-string convenience. |
NodePostgresPermissionsStoreOptions | Add connection-string convenience for permissions. |
createPostgresPool | Build the pg pool this entry builds for itself, with its idle-client 'error' listener attached; the caller owns and ends it. |
PostgresCheckpointerOptions | Re-export root checkpointer options. |
B4PostgresSaver | Re-export the saver class. |
postgresCheckpointer | Create a Node checkpointer. |
PostgresStoreOptions | Re-export root store options. |
PostgresPermissionsStore | Re-export the permissions store type. |
PostgresPermissionsStoreOptions | Re-export permissions options. |
createPostgresPermissionsStore | Create a Node permissions store. |
assertIdentifier | Re-export identifier validation. |
DEFAULT_SCHEMA | Re-export the default schema. |
DEFAULT_TABLE_PREFIX | Re-export the default table prefix. |
IDENTIFIER_PATTERN | Re-export the identifier pattern. |
SqlClient | Re-export the SQL client contract. |
SqlPool | Re-export the SQL pool contract. |
SqlResult | Re-export the SQL result contract. |
CreateThreadInput | Re-export thread creation input. |
PostgresThreadsStore | Re-export the threads store type. |
PostgresThreadsStoreOptions | Re-export thread options. |
Thread | Re-export the thread type. |
ThreadStatus | Re-export thread status. |
ThreadsStore | Re-export the threads-store contract. |
createPostgresThreadsStore | Create a Node threads store. |
InterruptGrantRecord | Re-export the approval-grant row type. |
InterruptGrantStore | Re-export the approval-grant store contract. |
InterruptGrantConsumption | Re-export the consume outcome type. |
PostgresInterruptGrantStore | Re-export the approval-grant store type. |
PostgresInterruptGrantStoreOptions | Re-export approval-grant options. |
createPostgresInterruptGrantStore | Create a Node approval-grant store. |
ClientToolCallRecord | Re-export the client tool call row type. |
ClientToolCallAnswer | Re-export the answer outcome type. |
ClientToolCallStore | Re-export the client tool call store contract. |
PostgresClientToolCallStore | Re-export the client tool call store type. |
PostgresClientToolCallStoreOptions | Re-export client tool call options. |
createPostgresClientToolCallStore | Create a Node client tool call store. |
Key contractsCopy link to section: Key contracts
PostgresStoreOptionsCopy link to section: PostgresStoreOptions
export interface PostgresStoreOptions {
readonly pool?: SqlPool
readonly ownsPool?: boolean
readonly assumeMigrated?: boolean
readonly schema?: string
readonly tablePrefix?: string
}Fields: @b4run/postgres-storage#.:PostgresStoreOptions
| Field | Type | Required | Description |
|---|---|---|---|
readonly pool | SqlPool | no | Supply the pool used by every store call. |
readonly ownsPool | boolean | no | End the supplied pool when this store closes. |
readonly assumeMigrated | boolean | no | Skip this instance's migration pass. |
readonly schema | string | no | Select the Postgres schema; must match IDENTIFIER_PATTERN. |
readonly tablePrefix | string | no | Prefix this application's tables; must match IDENTIFIER_PATTERN. |
Although pool is optional in the shared type, root factories fail without one. Use /node when connectionString or standard pg environment defaults should create an owned pool.
export interface PostgresPermissionsStoreOptions extends PostgresStoreOptions {
readonly config?: PermissionsFile
readonly mode?: PermissionMode
}export declare function postgresCheckpointer(
options?: PostgresCheckpointerOptions,
): B4PostgresSaverexport declare function createPostgresThreadsStore(
options?: PostgresThreadsStoreOptions,
): PostgresThreadsStoreexport declare function createPostgresPermissionsStore(
options?: PostgresPermissionsStoreOptions,
): PostgresPermissionsStoreexport interface NodePostgresStoreOptions extends PostgresStoreOptions {
readonly connectionString?: string
}export interface NodePostgresPermissionsStoreOptions extends PostgresPermissionsStoreOptions {
readonly connectionString?: string
}export declare function postgresCheckpointer(
options?: NodePostgresStoreOptions,
): B4PostgresSaverexport declare function createPostgresThreadsStore(
options?: NodePostgresStoreOptions,
): PostgresThreadsStoreexport declare function createPostgresPermissionsStore(
options?: NodePostgresPermissionsStoreOptions,
): PostgresPermissionsStoreBehavior contract postgres-storage.migration.instance-scoped
Migration memoization belongs to each store instance; assumeMigrated skips that instance's migration pass, while an unflagged instance begins a locked transaction.
Behavior contract postgres-storage.entry-split
The main entry links without Node built-ins for edge pools, while /node deliberately fails an edge bundle because it imports pg for connectionString convenience.
Migration and pool ownershipCopy link to section: Migration and pool ownership
Migration state is instance-scoped. In a per-request host, migrate an unflagged cold set of all three components, then set assumeMigrated only for the same database, schema, prefix, component, and current package schema. A wrong assertion fails on the first query. Checkpoint, thread, and permission migrations are separate.
Another process sees a durable permission grant only after that store calls load(). When you construct a custom permissions store, pass the resolved mode and config explicitly. B4.run does not overlay sibling configuration onto an already-created store.
Do not mark every store as owning one shared pool. An injected pool defaults to caller-owned and receives no error listener from B4.run. Setting ownsPool: true makes that store end it. A /node factory-created pool is owned, monitored, and closed by that store.
Schemas, table prefixes, and thread IDs organize data, but they are not tenant authorization boundaries. Rows are plaintext unless your database and infrastructure provide encryption.
Examples and related guidesCopy link to section: Examples and related guides
import { Pool } from "pg"
import {
createPostgresPermissionsStore,
createPostgresThreadsStore,
postgresCheckpointer,
} from "@b4run/postgres-storage"
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
pool.on("error", (error) => console.warn("Postgres pool error", error))
const checkpointer = postgresCheckpointer({ pool })
const threadsStore = createPostgresThreadsStore({ pool })
const permissionsStore = createPostgresPermissionsStore({ pool })
await Promise.all([checkpointer.ready(), threadsStore.ready(), permissionsStore.ready()])
// During application shutdown:
await Promise.all([checkpointer.close(), threadsStore.close(), permissionsStore.close()])
await pool.end()Continue with Persistence and Tenancy, Production Topology, and Edge and Hono.