pgmem
Operations

Deployment

Provisioning Postgres, the schema, and the worker in production.

pgmem is a library plus a SQL layer — there's no separate service to run. Deploying it means: a Postgres with pgvector, the schema applied, your agent app importing the SDK, and background projection workers where you use derived memory views.

Prerequisites

  • A production PostgreSQL with the pgvector extension available.
  • Your agent app, with the pgmem SDK as a dependency.

Steps

Provision Postgres + pgvector

Use any managed or self-hosted Postgres with pgvector enabled. The embedding dimension is fixed at 1536 by the schema.

Apply the schema

Apply the schema to your production database with the idempotent SQL installer (safe to re-run on every deploy):

psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f sql/migrations/install.sql

Self-hosted Postgres can instead install pgmem as a first-class extension (CREATE EXTENSION pgmem) from the packaged sql/extension/pgmem--*.sql. Either way, gate releases on the schema being current — see Versioning & migrations.

Connect the app and size the pool

Construct one PgMem per process at startup and reuse it. Size the pool for your concurrency — max_size >= 2 is required for add_episode_bulk, compact_async, and concurrent application/worker activity. Size it ≥ the number of groups you ingest concurrently.

from pgmem import PgMem, PgMemConfig, PoolConfig

mem = await PgMem.create(
    dsn, embedder=embedder, llm=llm,
    config=PgMemConfig(pool=PoolConfig(max_size=20)),
)

Run projection maintenance workers

Claim vector and graph projections refresh off the turn. Run the promotion worker as a long-lived task — in the same process or a dedicated one. Multiple workers are safe. If claims use retention deadlines, run the retention worker from the same scheduler.

from pgmem import ClaimRetentionWorker, PromotionWorker

promotion = PromotionWorker(mem)
await promotion.recover()                 # requeue leases from a previous crash
asyncio.create_task(promotion.run())      # poll + process in the background
asyncio.create_task(ClaimRetentionWorker(mem).serve(poll_interval=60))

See Run the promotion worker.

Notes

  • Agent workers are stateless. All durable state lives in Postgres, so you can scale workers horizontally and restart them freely; session.resume recovers an interrupted session. See LiveKit / voice agents.
  • Providers are injected, not configured — keep API keys in your secret manager and pass the embedder/LLM into PgMem; PgMemConfig stays pure, loggable data.

On this page