- The memory pipeline lists the same chat and participant cards many times
while sizing a run's batches. Serve those lists from an LRU cache in the
memory store (MEMORY_CARD_CACHE_ENTRIES, default 4096, 0 disables; 5 min
TTL). Card writes of a batch or merge group invalidate their chat and
users; admin and batch writes clear the cache; a generation counter keeps
a list read during an invalidation out of the cache. Settings and agent
listings still read Postgres.
- Dialog turns no longer wait on the card usage UPDATE. Recalled cards go
to an in-memory journal that a worker applies in one statement every
30 s and on shutdown; updated_at still moves for deferred
reconsolidation.
- The flush worker logs cache statistics every 5 minutes for sizing.
Summary
Two memory-card paths put avoidable load on Postgres:
UPDATE memory_cardsthat records usage. Each update also movesupdated_at, which is indexed, so it is never a HOT update and rewrites every index entry of the card, including its HNSW vector.RAM cache of visible-card lists
MemoryCardCache(storage): LRU keyed by chat, thread, user, own-DM flag and limit; capacity fromMEMORY_CARD_CACHE_ENTRIES(default 4096,0disables), entries expire after 5 minutes.list_visible_cards_cachedbehindMemoryRunStore::list_visible_cards). The settings WebApp and agent tools keep reading Postgres, so a card a user deletes never reappears from the cache.Write-behind card usage
MemoryCardUsageJournalcollects recalled card ids with their latest use time and use count. Dialog input records into it without waiting on Postgres.memory-card-usage-flushworker applies the journal in oneUPDATE ... FROM unnest(...)every 30 s and once more on shutdown (ancillary phase, after the dialog workers stop). A failed flush is merged back into the journal for the next attempt.updated_atstill moves with usage; deferred reconsolidation selects recently touched cards.Sizing
The flush worker logs
memory card cache stats(entries, bytes, hits, misses, expired, evictions, invalidated) every 5 minutes. The cache size is configuration only, so it can be tuned after measuring production traffic.Compatibility
record_card_retrievalis replaced byrecord_card_usage(&[MemoryCardUsage]); the only production caller (dialog input) now uses the journal.Deployment risk and verification plan
memory card cache statsfrom the logs after 10–30 minutes and compare hits with misses; compare calls and total time of the visible-card list statement and of the usageUPDATEinpg_stat_statementsbefore and after; confirmuse_countkeeps growing for recalled cards; check dialog latency and failures.Verification
cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspace.0disabling.record_card_usageand checksuse_countandlast_used_at.