NewRelease 0.12.3 is out: Engine v0.12.3, Dashboard 0.5.2, Helm 0.12.3, the four SDKs, CLI 0.8.2 and MCP 0.12.3Release 0.12.3 is outSee what's new →
COMPARE · VECTOR DB

Dakera vs pgvector: you already run Postgres, so here is what you would still write

pgvector turns Postgres into a vector store, and for vectors that belong next to relational data it is hard to beat. Agent memory asks for more than nearest-neighbour search. This page puts the SQL and application code for hybrid search, reranking and decay beside the Dakera call that does the same.

Reviewed October 2026

88.2%
LoCoMo Recall@20, 1,536 questions: does retrieval surface the answer. Method
1 call
hybrid retrieval, rerank and decay-aware ranking, with no SQL to maintain
0.87 ms
vector search p50 at recall@10 0.998 (50k vectors, CPU only, v0.12.0)
18
languages with full-text stemming, plus CJK bigrams (v0.12.0)

When pgvector is exactly right

pgvector is an open-source Postgres extension under the PostgreSQL licence. It stores vectors with the rest of your data and supports exact and approximate search with HNSW and IVFFlat indexes, plus half-precision, binary and sparse vector types and six distance operators. Because it lives in Postgres you get ACID transactions, joins and point-in-time recovery, and it comes preinstalled with many hosted Postgres providers. If your embeddings describe rows you already keep in Postgres, adding a column is the simplest design.

What you would still write

For agent memory, the vector index is the first of several pieces. pgvector's own documentation points to Postgres full-text search and Reciprocal Rank Fusion for hybrid retrieval; the rest is your code.

Pieces of an agent memory system
Capabilitypgvector + your codeDakera
Embedding modelYour serviceOn-device
Hybrid retrieval and fusiontsvector, GIN index, RRF queryYour SQLYes
Cross-encoder rerankingYour serviceYes
Decay, TTL and expiryYour SQL and a jobYes
Deduplication and consolidationYour codeYes
Entity extraction and graphYour pipelineYes
Agents, sessions, scoped keysYour schema and rolesYes
MCP tools and a memory dashboardYour buildYes

Write path: schema, insert, decay

The pgvector schema is valid, ordinary Postgres. Decay becomes a scheduled DELETE that you own and tune.

pgvector (SQL)
CREATE EXTENSION vector;

CREATE TABLE memories (
  id bigserial PRIMARY KEY,
  agent_id text NOT NULL,
  content text NOT NULL,
  importance real DEFAULT 0.5,
  created_at timestamptz DEFAULT now(),
  embedding vector(1024),
  tsv tsvector GENERATED ALWAYS AS
    (to_tsvector('english', content))
    STORED
);
CREATE INDEX ON memories USING hnsw
  (embedding vector_cosine_ops);
CREATE INDEX ON memories USING gin (tsv);

INSERT INTO memories (agent_id, content,
  importance, embedding)
VALUES ($1, $2, $3, $4);

-- decay: a job you schedule yourself
DELETE FROM memories
WHERE importance * exp(-extract(epoch
  FROM now() - created_at) / 604800.0)
  < 0.01;
Dakera (Python)
from dakera import DakeraClient

client = DakeraClient(
    "http://localhost:3000", api_key=KEY)

client.store_memory(
    agent_id="support",
    content="Maria prefers email",
    importance=0.8,
)

# decay is server-side configuration
client.decay_update_config(
    strategy="exponential",
    half_life_hours=168,
    min_importance=0.01,
)

Dakera supports six decay curves (exponential, linear, step, power-law, logarithmic, flat) and spaced-repetition TTL extension. See the Python SDK.

Read path: hybrid search, rerank, decay

Left: a reciprocal-rank-fusion query over vector and full-text results, weighted by importance and age, then a cross-encoder run in your application. Right: the call that does it.

pgvector (SQL + app)
WITH v AS (
  SELECT id, row_number() OVER (
    ORDER BY embedding <=> $1) AS r
  FROM memories WHERE agent_id = $2
  ORDER BY embedding <=> $1 LIMIT 50),
k AS (
  SELECT id, row_number() OVER (
    ORDER BY ts_rank_cd(tsv, q) DESC) AS r
  FROM memories,
    websearch_to_tsquery('english', $3) q
  WHERE agent_id = $2 AND tsv @@ q
  ORDER BY ts_rank_cd(tsv, q) DESC
  LIMIT 50)
SELECT m.id, m.content,
  (COALESCE(1.0 / (60 + v.r), 0)
   + COALESCE(1.0 / (60 + k.r), 0))
  * m.importance
  * exp(-extract(epoch FROM now()
      - m.created_at) / 604800.0) AS score
FROM memories m
LEFT JOIN v USING (id)
LEFT JOIN k USING (id)
WHERE v.id IS NOT NULL OR k.id IS NOT NULL
ORDER BY score DESC LIMIT 20;

# then, in your application:
rows = conn.execute(SQL, params).fetchall()
pairs = [(query, r[1]) for r in rows]
scores = reranker.predict(pairs)
top = sorted(zip(scores, rows),
             key=lambda x: -x[0])[:10]
Dakera (Python)
response = client.recall(
    agent_id="support",
    query="How do we contact Maria?",
    top_k=10,
)
for m in response.memories:
    print(m.content, m.score)

# BM25 + HNSW, RRF fusion, cross-encoder
# rerank and decay-aware scoring all ran
# in that one call, on-device.

The SQL assumes your application computes the query embedding and passes it as $1. Reranker weights, decay constants and the language configuration are yours to choose and maintain.

What v0.12.0 adds for Postgres teams

  • Multilingual: the SQL above uses one text search configuration, 'english', and you pick another per language. Dakera embeds with bge-m3 across 100+ languages in one space and takes a per-request lang. See Multilingual.
  • Multimodal: file attachments, on-device speech to text and visual recall over document pages. See Multimodal.
  • Debuggable ranking: rerank_report in every response, plus a Recall lab in the dashboard that shows why each memory ranked where it did.
  • Operations: encrypted, compressed backups, /health/ready, and dakera downgrade to roll back to v0.11.108.
They can sit side by side. Keep your customers, orders and permissions in Postgres, and keep agent memory in Dakera. Nothing in Dakera depends on Postgres, and one more service to run is the cost of the split.

When to choose pgvector, and when Dakera

Choose pgvector if

  • Your vectors belong next to relational rows, with joins and transactions between them.
  • Postgres is already your operational database, and you do not want another datastore.
  • Your host or managed Postgres already offers it, with the backups and failover you rely on.
  • You want to write and tune the ranking SQL yourself.

Choose Dakera if

  • You want memory behaviour (decay, consolidation, sessions, graph) without building it in SQL.
  • Retrieval needs a reranker, and you would rather not host one.
  • You need multilingual or multimodal memory behind one API.
  • You want MCP tools, SDKs in four languages and a dashboard out of the box.

Prefer managed? Dakera Cloud is coming. Join the waitlist.

Frequently asked questions

Yes. Combine vector distance with Postgres full-text search and fuse the ranks, as in the query above. You write and maintain that query, along with the reranking and decay around it.

Does Dakera use Postgres?

No. Dakera is a single self-hosted binary with its own storage, so there is no database to provision beside it.

How do I move memories out of Postgres?

Select the content, importance and timestamps, start Dakera with the Quickstart command and send them through the batch memory endpoint. Dakera embeds on-device, so the stored vectors stay behind.

How should I read the LoCoMo figure?

Dakera reports Recall@20: whether the answer is among the top 20 retrieved memories, with no LLM in the retrieval path. It measures memory retrieval, so this page does not set it against a vector extension.

Self-hosted is free

Run Dakera on your own infrastructure.

One binary with its models baked in and no per-call fees. Start it with one Docker command and see it for yourself.

Prefer managed hosting? Join the Dakera Cloud waitlist →