How Remem Works
Remem’s core is a single Rust service, remem-server (port 4545): the REST API (Axum), the MCP server (Streamable HTTP at /mcp), and the embedded storage engine, all in one process. No external database, no Qdrant/Postgres/Redis dependency for the core.
For MCP clients that only speak stdio (Claude Desktop, Claude Code), remem-mcp is a small companion binary you run directly — it holds no data itself and simply forwards MCP tool calls to remem-server over HTTP. Clients that speak MCP Streamable HTTP can skip it and talk to remem-server’s /mcp route directly.
Storage engine
Section titled “Storage engine”remem-server embeds five purpose-built indexes:
HNSW vector index
Section titled “HNSW vector index”all-MiniLM-L6-v2 embeddings (384 dimensions) generated locally via fastembed. No external embedding API — embeddings are computed in the same process. The HNSW index enables approximate nearest-neighbour vector search for semantic queries.
CSR relationship graph
Section titled “CSR relationship graph”A compressed sparse row graph where nodes are memories and edges are typed connections (relationship_type: related_to, caused_by, part_of, references, contradicts, supports, similar_to, derived_from). Edges are written automatically by the auto-discovery worker and explicitly via the connections API.
Time-windowed range queries — e.g. listing memories created or accessed within a date range.
Inverted tag index
Section titled “Inverted tag index”Tag-based lookup with soft-delete support, used by keyword search and tag filters.
LSM-tree key-value store
Section titled “LSM-tree key-value store”Durable, write-ahead-logged storage for memory content and metadata. Every write goes through the WAL before being acknowledged, so a crash mid-write never loses committed data. Indexes checkpoint to disk periodically (checkpoint_interval_secs, default 300s / 5 minutes) rather than on every write — but reads are read-after-write consistent because reads hit the in-memory segment first, not the on-disk checkpoint.
Write path
Section titled “Write path”store_memory(content, memory_type, tags, importance, emotional_valence, arousal) │ ├─ embed(content) → 384-dim vector [fastembed, in-process] ├─ write(payload) → LSM-tree [WAL-backed, durable] ├─ arousal >= 0.8? → force-promote to long_term, │ floor importance at 0.9, set flashbulb_until [flashbulb protection] └─ dispatch(auto-discovery) → background worker │ ├─ query HNSW index (top-K similar memories) ├─ filter by auto_discovery_threshold (default: 0.7) └─ write connections → CSR graph (capped at auto_discovery_top_k, default 5)The API returns after the LSM write (and any flashbulb promotion, which is synchronous). Auto-discovery of connections is asynchronous — store_memory returns before it completes.
Read path
Section titled “Read path”Semantic search:
- Embed the query
- Query HNSW index for top-K nearest memories
- Return ranked results
Hybrid search:
- Embed the query
- Query HNSW index (semantic score)
- Query inverted index (keyword score)
- Combine semantic and keyword scores
- Return ranked results
Graph traversal:
- Start from a memory node
- Walk outgoing edges in the CSR graph (breadth-first)
- Return nodes at each depth level
Memory lifecycle
Section titled “Memory lifecycle”| Stage | Trigger | Effect |
|---|---|---|
| Short-term | memory_type: "short_term" + ttl set | Expires automatically at ttl |
| Long-term | memory_type: "long_term", promotion, or flashbulb creation | Persists indefinitely (subject to importance decay and active forgetting) |
| Promotion | Manual (promote_to_longterm / POST .../promote), or automatic at creation for flashbulb memories (arousal >= 0.8) | Short-term → long-term |
| Importance decay | Background task, daily | Long-term importance decrements ~0.5%/day; flashbulb memories exempt while protected |
| Active forgetting | Background task, daily | health decays (short-term −8/day, long-term −2/day since last recall); recall boosts health +10 (capped 100); memory is hard-deleted at health 0. Flashbulb memories exempt while protected |
| Archive | hard=false (default) on delete | Hidden from search, retained in storage |
| Delete | hard=true on delete | Removed from all indexes |
Emotional memory & flashbulb protection
Section titled “Emotional memory & flashbulb protection”store_memory accepts emotional_valence (-1.0 to 1.0) and arousal (0.0 to 1.0). A memory created with arousal >= 0.8 becomes a flashbulb memory: it’s force-promoted to long_term, its importance is floored at 0.9, and it’s exempt from importance decay and active forgetting for 30 days (flashbulb_until). This only happens at creation time — raising arousal later via update_memory does not retroactively apply it. See Memory Lifecycle for details.
Background tasks
Section titled “Background tasks”Lifecycle tasks run as Tokio tasks inside remem-server — no separate worker process is needed. There is no single unified interval; each task has its own schedule, configured under [tasks] in remem-server.toml:
| Task | Default interval |
|---|---|
expire_short_term | 5 minutes |
apply_importance_decay | daily |
active_forgetting | daily |
consolidate_similar | weekly |
cleanup_archived | monthly |
discover_connections | hourly |
See Configuration for the full [tasks] config, and Memory Lifecycle for what each task does.
