PostgreSQL + pgvector
If your team already runs PostgreSQL, Recall can keep its memory there, with the pgvector extension. Every Recall capability works on it: typed facts, corrections, history, keyword search, cached reads, and agent resume, with each agent write checked against its lease inside the write's own transaction.
Before you start
- PostgreSQL 13 or later with pgvector 0.6.0 or later. pgvector 0.8.0 or later is
recommended (see Good to know). Managed PostgreSQL services that offer
the
vectorextension work too. - A role with
CREATEon the database. Thevectorextension must be installed, or the role must be allowed to create it. recall0.19.0 or later, 0.21.0 or later for agent actions and fenced writes:brew install polign/tap/recallorpip install polign-recall.
Run the memory server on PostgreSQL
-
Start PostgreSQL with pgvector, if it is not running yet:
docker run -d -e POSTGRES_PASSWORD=recall -p 5432:5432 pgvector/pgvector:pg17
-
Add Recall to Claude Code as an MCP server:
claude mcp add recall \ -e RECALL_BACKEND=pgvector \ -e DATABASE_URL=postgres://postgres:recall@localhost:5432/postgres \ -- recall mcp -write
Put the password in
PGPASSWORDinstead of the URL if you prefer. Add-agentfor the agent resume tools. Other MCP hosts take the same command and variables, or the flagsrecall -backend pgvector -url postgres://... mcp -write. -
Restart Claude Code and ask it to remember something. The first write creates the
recallschema and the collection's table.
recall setup and the Recall plugin set up
a polign_db connection. With PostgreSQL, add the MCP server yourself as in step 2.
Use it from Go
import (
"github.com/Polign/recall"
"github.com/Polign/recall/backend/pgvector"
)
backend, err := pgvector.New(pgvector.Config{
URL: os.Getenv("DATABASE_URL"),
})
defer backend.Close()
client, err := recall.NewClient(recall.Config{
Backend: backend,
Collection: "team_memory",
Registry: recall.DefaultRegistry(),
Embedder: recall.LexicalEmbedder{},
})
pgvector.Config also takes a Schema (default recall),
the TextSearchConfig for keyword search (default english), and a
Pool to share a pgx connection pool you already have. The package uses
pgx, which a program pulls in
only by importing it.
What gets stored
| Recall | PostgreSQL |
|---|---|
| A collection | A table in the recall schema, named after the collection, created on the first write with the first vector's size |
| An event | A row: the event ID, the vector, and the metadata as jsonb |
| Indexes | HNSW on the vector (cosine), GIN on the metadata, a generated tsvector for keyword search, and an index on observation time |
| Bookkeeping | recall_collections maps each collection to its table and counts its writes, which is what cached reads check; recall_leases holds agent leases |
Agent resume and fenced writes
Leases are rows in recall_leases, taken and renewed by the database's own
clock, so recall mcp -agent and Client.Resume work as they do on
polign_db. Each agent write reads its lease row with FOR SHARE in the same
transaction as the write. A process that stalled past its lease is refused even when its own
clock still says the lease is fresh, and a takeover waits for an in-flight write to commit.
See Resume for how actions and leases fit together.
Good to know
- A collection takes its vector size from the first write. Changing embedders needs a new collection.
- Every write to a collection updates that collection's revision row, so writes to one collection run one at a time. That is invisible at conversation pace; a bulk import notices.
- Keyword search uses the
englishtext search configuration unlessConfig.TextSearchConfignames another. It is fixed when a collection is created. - On pgvector older than 0.8.0, a filtered vector search can return fewer hits than asked for, because the index stops scanning before the filter applies. 0.8.0 keeps scanning until the filter is satisfied.
If something goes wrong
| What you see | What to do |
|---|---|
unknown backend "pgvector" | Your recall is older than 0.19.0. Upgrade it. |
the vector extension is not installed and could not be created | Install pgvector on the server, then run CREATE EXTENSION vector as a role that may. |
holds 256-dimensional vectors, not 384 | The collection was created with another embedder. Use a new -collection when you change embedders. |
lease_held on resume | Another process holds the agent, or one died less than a lease time ago. Wait for the lease to expire. |
Source & license
The PostgreSQL backend is part of Recall, open source under the Apache License 2.0, in github.com/Polign/recall. Bug reports and pull requests go there.