Retention GC
A background worker runs every hour, each pass bounded by a batch cap so it never stalls the gossip hot path:- Expired diffs are deleted once they are past
diff_retention(the propagation TTL plus a 24-hour grace). Note that a diff’s TTL is a propagation TTL only — it halts the gossip walk, not storage retention. - Dead deliveries are compacted: rows past
delivery_retention(30 days) whose diff is itself dead and already promoted or consolidated are dropped. The worker only drops provably-dead rows; it never updates a live one, so append-only semantics hold. - A2A task rows ride the same pass: terminal task rows past
a2a.task_retention_days(default 30 days) are cut, and an Agent-scoped erasure removes the agent’s task rows too — see A2A tasks & streaming.
In-memory eviction and cold tiering
The in-memory graph is bounded independent of corpus size. When the node count exceeds the ceiling (1,000,000 by default) or a node has been idle pastcell_idle_eviction (7 days), the eviction worker
removes it from the HNSW graph and re-links its neighbors — but keeps the PostgreSQL row. An
evicted node is a cache miss that re-loads on next access.
At the ceiling, eviction drops the coldest nodes first and keeps the hottest resident. Beacon, L2,
and Agent nodes are eviction-exempt — they are few and load-bearing for routing and positions.
This is why the deployment memory budget is sized against the node ceiling, not the corpus. PostgreSQL
may hold many more nodes than RAM. See /operations/deployment-operations.
Tombstones and delete propagation
delete_node is no longer a local operation. It:
1
Persists a tombstone first
So a crash mid-delete re-drives the delete on restart rather than leaving it half-done.
2
Removes the node locally
Deletes the PostgreSQL row (cascading edges) and evicts the node from the in-memory graph.
3
Propagates a tombstone diff
Seeds a
Tombstone-type diff at the deleted node’s embedding, so it traverses the same semantic
neighborhood the original reached — energy-bounded, no flood.delete_node
is idempotent: if a tombstone already exists for the target, it is a no-op.
Compliant erasure
erase(Agent) or erase(Project) is the compliant, GDPR-style delete. It enumerates and removes
everything for a scope across all tiers — PostgreSQL rows, the in-memory graph, and promoted
L1/L2 aggregates (whose centroids are recomputed without the erased cells, or superseded) — propagates
a tombstone per node so other agents’ caches drop the content, and returns an auditable erasure
certificate with per-tier counts and a digest. Erasure is bounded and idempotent: re-running it
yields the same certificate with zero additional removals.
Re-embed migration
Changing the embedding model puts the stored vectors in the wrong space, and the server fail-safes by refusing to load. The re-embed migration is the path forward: it streams every node, re-embeds it with the new model, re-links it in the graph, rewrites the stored model metadata, and rebuilds the snapshot. The resulting graph’s recall matches a fresh build. V1 runs this offline (stop writes, re-embed, swap); an online dual-read cutover is a future enhancement.Defaults
The retention TTLs are reloadable with
SIGHUP. See /operations/configuration.