---
title: "Memory Scoring & Decay"
description: "How ZeroMemory ranks memories using blended scoring — similarity, importance, and recency"
canonical: "https://docs.ainative.studio/docs/zeromemory/scoring"
last-updated: "2026-10-03T21:47:10.764Z"
---

# Memory Scoring & Decay

Source: https://docs.ainative.studio/docs/zeromemory/scoring

> How ZeroMemory ranks memories using blended scoring — similarity, importance, and recency

# Memory Scoring & Decay

ZeroMemory uses a blended scoring algorithm to rank memories during recall. This ensures the most relevant, important, and recent memories surface first.

## Blended Scoring Formula

```
final_score = (similarity × W_sim) + (importance × W_imp) + (recency × W_rec)
```

Default weights:
- **W_sim** = 0.5 (semantic similarity)
- **W_imp** = 0.3 (importance)
- **W_rec** = 0.2 (recency)

### Similarity Score (0.0–1.0)

Cosine distance between the query embedding and each memory's embedding. Powered by pgvector HNSW indexes for sub-millisecond search.

### Importance Score (0.0–1.0)

Set at storage time via the `importance` parameter. Can also be adjusted:
- **Auto-boost**: Importance increases by 0.05 each time a memory is accessed (capped at 1.0)
- **Manual**: Update via the API

### Recency Score (0.0–1.0)

Decays over time using exponential decay based on **days since last access** (not creation):

```
effective_importance = importance × exp(-decay_rate × days_since_access)
```

#### Per-Type Decay Rates

| Memory Type | Decay Rate | Half-Life | Effective Zero (~0.05) |
|-------------|-----------|-----------|----------------------|
| **Working** | 0.5 | ~1.4 days | ~6 days |
| **Episodic** | 0.1 | ~6.9 days | ~30 days |
| **Semantic** | 0.02 | ~34.7 days | ~150 days |

:::tip Accessing resets the clock
Every time a memory is accessed (recalled, searched, or referenced), `days_since_access` resets to 0. Frequently-used memories never decay.
:::

#### Soft-Delete Threshold

Memories whose effective importance drops below **0.05** are soft-deleted (state → `archived`). They remain in the database but are excluded from recall results. Consolidation can still reference archived memories.

#### Retention Examples

A semantic memory with importance 0.8:
- After 1 week: `0.8 × exp(-0.02 × 7)` = **0.69** (still active)
- After 1 month: `0.8 × exp(-0.02 × 30)` = **0.44** (still active)
- After 5 months: `0.8 × exp(-0.02 × 150)` = **0.04** (archived)

An episodic memory with importance 0.5:
- After 1 day: `0.5 × exp(-0.1 × 1)` = **0.45** (active)
- After 1 week: `0.5 × exp(-0.1 × 7)` = **0.25** (active)
- After 1 month: `0.5 × exp(-0.1 × 30)` = **0.02** (archived)

## Memory Tiers & Consolidation

| Tier | Typical Lifespan | Consolidation |
|------|-----------------|---------------|
| **Working** | Hours | Auto-consolidates to episodic after session ends |
| **Episodic** | Days–weeks | Frequently accessed episodic memories promote to semantic |
| **Semantic** | Permanent | Core knowledge — highest importance, slowest decay |

Consolidation happens automatically based on:
1. **Access frequency**: Memories accessed 3+ times promote faster
2. **Importance threshold**: Memories with importance > 0.7 promote faster
3. **Time in tier**: Working memories consolidate after ~4 hours of inactivity

## Example: How Scoring Works

A user asks: "What programming language does Alice prefer?"

| Memory | Similarity | Importance | Recency | Final Score |
|--------|-----------|------------|---------|-------------|
| "Alice prefers Python for backend" | 0.92 | 0.8 | 0.9 | **0.88** |
| "Alice mentioned Rust is interesting" | 0.75 | 0.4 | 0.3 | 0.56 |
| "Backend team uses Python and FastAPI" | 0.70 | 0.5 | 0.7 | 0.64 |

The first memory wins because it has high similarity AND high importance AND was accessed recently.

## Tuning Tips

- **Set importance explicitly** for critical facts (preferences, decisions, constraints)
- **Use memory_type wisely**: `working` for current task context, `episodic` for interactions, `semantic` for permanent knowledge
- **Tag memories** so you can filter during recall for better precision
- **Reflect periodically**: The `/reflect` endpoint consolidates and synthesizes patterns

## GraphRAG Scoring

When using the [GraphRAG endpoint](/docs/guides/graphrag), an additional graph proximity score is blended:

```
graphrag_score = (vector_score × (1 - graph_weight)) + (graph_proximity × graph_weight)
```

Default `graph_weight` is 0.3 (70% vector, 30% graph). Tune higher for queries about relationships, lower for topical searches.
