How Pinned Pages Affect Retention in ai-memory: A Complete Technical Guide
Pinned pages are completely immune to decay in ai-memory—the forget sweep explicitly excludes any row where pinned = true, guaranteeing permanent retention unless manually deleted.
The ai-memory system implements a tiered memory architecture where most content ages out according to configurable decay rules. However, certain pages require indefinite persistence. This article examines exactly how the pinned flag operates within the decay subsystem, with direct reference to the implementation in akitaonrails/ai-memory.
The Decay Subsystem and Pinned Exclusion
The retention mechanism centers on a periodic "forget sweep" that evaluates pages for eviction. The sweep queries decay candidates based on tier (typically episodic) and critically filters out pinned content.
In crates/ai-memory-store/src/reader.rs, the decay candidate selection explicitly excludes pinned rows:
// sweep itself filters by tier (only `episodic`) + pinned flag,
// "SELECT … tier, pinned …" (see line 3243)
This query construction ensures that pinned = true rows never enter the decay pipeline. The database column acts as a hard gate—no subsequent decay logic ever processes these pages.
Automatic Pinning for Slot Pages
Pages written under the internal _slots/ namespace receive automatic pinning. This design choice treats slot pages as system-critical infrastructure that must survive all retention policies.
The unit test slot_pages_are_pinned_automatically in crates/ai-memory-wiki/src/wiki.rs validates this behavior:
assert!(candidates[0].pinned, "slot pages should be decay-immune"); // line 3318
Any path prefix-matched to _slots/ triggers this automatic pinning at write time, without requiring explicit front-matter configuration.
Manual Pinning via Front-Matter
Users can pin arbitrary pages by setting pinned: true in front-matter. The wiki writer extracts this value and persists it to the database.
In crates/ai-memory-wiki/src/wiki.rs at line 560:
let pinned = meta.pinned;
The writer then propagates this boolean into the store's pinned column, making the page decay-immune immediately upon persistence.
Practical Code Examples
Pin a Page via Front-Matter
use ai_memory_wiki::Wiki;
use serde_json::json;
let path = "notes/important.md";
let body = "Critical design decisions.";
let meta = json!({
"title": "Important Notes",
"pinned": true // <- retention-immune
});
let req = wiki::write_page_req(path, body, meta);
wiki.write_page(req).await.unwrap();
Create an Auto-Pinned Slot Page
let slot_path = "_slots/project-context.md";
let body = "Current project context…";
wiki.write_page(wiki::write_page_req(slot_path, body, json!({})))
.await
.unwrap(); // pinned: true applied automatically
Verify Decay Candidate Exclusion
let candidates = store.reader.decay_candidates(ws, proj).await.unwrap();
assert!(candidates.iter().all(|c| !c.pinned)); // pinned pages absent
Key Implementation Files
| Component | File | Significance |
|---|---|---|
| Wiki writer | crates/ai-memory-wiki/src/wiki.rs |
Extracts meta.pinned from front-matter (line 560); validates slot pinning (line 3318) |
| Decay candidate query | crates/ai-memory-store/src/reader.rs |
Excludes pinned rows from sweep (lines 3243-3245) |
| Decay engine | crates/ai-memory-store/src/decay.rs |
Applies aging formulas only to non-pinned pages |
| Slot write path | crates/ai-memory-store/src/writer.rs |
Implicitly sets pinned: true for _slots/ pages |
Summary
- Pinned pages are decay-immune: The forget sweep filters
pinned = trueat the query level inreader.rs - Two pinning mechanisms: Explicit front-matter flag or automatic
_slots/namespace detection - Permanent retention: Pinned pages persist until explicit deletion, regardless of access patterns or age
- Validated by tests:
slot_pages_are_pinned_automaticallyguarantees the behavior
Frequently Asked Questions
Can a pinned page ever be deleted?
Yes. Pinning only prevents automatic decay eviction through the forget sweep. Explicit deletion operations—whether through API calls or direct database operations—still remove pinned pages. The immunity applies solely to the automated retention system.
What happens if I unpin a previously pinned page?
Removing pinned: true from front-matter and rewriting the page clears the database flag. On subsequent decay sweeps, the page becomes eligible for evaluation based on its tier, age, and access patterns. There is no retroactive decay—eligibility begins from the unpinning moment.
Are there performance implications for pinning many pages?
The decay candidate query in reader.rs must scan and filter all rows in the tier, including pinned ones. While the pinned column likely has an index, extremely large pinned populations could increase query overhead. However, since pinned pages never enter the expensive decay calculation pipeline, the overall cost is typically lower than managing equivalent unpinned content.
Why does the _slots/ namespace receive automatic pinning?
Slots serve as structured, system-addressable memory locations—often containing active context, tool configurations, or session state. Automatic pinning ensures these operational pages survive across decay cycles without requiring manual front-matter maintenance, reducing the risk of accidental context loss during long-running sessions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →