Recency Decay: Teaching AI Memory to Forget on Purpose
An exponential half-life applied to retrieval scores fixes more relevance bugs than a better embedding model. How to tune the decay constant without erasing durable facts.
A memory store that never forgets converges on being useless. Not because it runs out of disk, but because every stale fact keeps competing for the same top-k slots as the fact that replaced it. The fix is one multiplicative term on the retrieval score, and the shape of that term should be exponential:
recency_weight = exp(-ln(2) * age_days / half_life)The ln(2) is there so that half_life means what the name says. Substitute age_days = half_life and the exponent becomes -ln(2), so the weight is exactly 0.5. Two half-lives gives 0.25, three gives 0.125. You get a parameter you can reason about in plain language ("this class of memory loses half its weight every 30 days") instead of a dimensionless lambda you tune by trial and error.
The other useful property is that exponential decay is memoryless. The ratio of weights between two memories depends only on the difference in their ages, never on when you happen to run the query. A 30-day-old entry always outranks a 60-day-old entry by the same factor of two, today and next March. Ranking stays stable as the whole corpus ages together.
Numbers that actually work
Half-life is not a global constant. It is a property of the memory class, and there are roughly three classes worth distinguishing:
- Volatile, 14 to 30 days. Current sprint, the bug being chased this week, which branch is deployed, what the user is trying to finish today. At a 14-day half-life, something from six weeks ago retains 0.125 weight, which is low enough to lose to anything current and high enough to still surface if the store has nothing better.
- Semi-stable, roughly 180 days. Tech stack choices, team composition, architectural decisions, the shape of a project. These change, but on a quarterly rhythm rather than a weekly one. A year-old entry keeps about 0.25 weight.
- Durable, no decay at all.The user's name, their timezone, that they are red-green colorblind, that they prefer tabs. Applying any decay to these is a bug. Multiplying by 1.0 is the correct behavior and it should be an explicit branch in the code, not a very long half-life.
Note that these are half-lives for a weight, not deletion schedules. Nothing is removed. A volatile memory from two years ago has a recency weight near zero but is still there, still queryable by explicit filter, still auditable.
Why linear decay and TTL are both wrong
Linear decay, 1 - age/max_age, has a cliff. It hits zero at a fixed age and goes negative past it unless you clamp. Worse, the ratio between two memories is not age-difference-invariant: with max_age = 365, a 10-day and a 20-day memory differ by 3%, while a 350-day and a 360-day memory differ by 67%. Same ten-day gap, wildly different treatment. Ranking becomes a function of when you ask.
Hard TTL is worse in a specific and expensive way. It converts a gradual confidence reduction into a discontinuity. On day 89 the fact is fully present; on day 91 it does not exist and the model has no indication anything was ever there. That produces confidently wrong answers rather than uncertain ones, and it destroys provenance you may need later. TTL is a storage policy masquerading as a relevance policy.
The classification problem is the actual hard part
The formula is arithmetic. Deciding which of the three classes a new memory belongs to is where real systems get stuck, and there is no clean solution. Three approaches, in ascending order of cost:
Lexical hinting.Presence of "currently," "this week," "right now," "we just" correlates with volatility. Present-progressive framing does too. This is cheap, catches maybe 60% of cases, and produces confident errors on the rest.
Ask the writing model.When a tool call stores a memory, have the caller supply a volatility field as part of the arguments. The model that just had the conversation is in the best position to know whether "Marc is on the payments team" is a durable fact or this quarter's rotation. The cost is that you are trusting an LLM's self-report, and it will default to whatever the schema description nudges it toward.
Infer from revision history.If entries about a given entity have historically been superseded every few weeks, that entity's facts are volatile. This is the most accurate signal and it requires a store that already has months of supersession data, which means it cannot help you on day one.
The failure mode you will actually hit
Decay buries a still-true fact. The user mentioned in January that the deploy pipeline requires a manual approval step. It is July, nothing has contradicted it, it is still true, and it now sits at 0.03 recency weight because it got classified volatile. The model does not surface it, does the wrong thing, and the user reasonably concludes the memory system is broken.
Two mitigations, both cheap. First, refresh on access: when a decayed memory gets retrieved and the conversation does not contradict it, bump its effective timestamp. Repeated usefulness is evidence of durability, and this is the same intuition behind spaced repetition. Second, and more important, put a floor on the weight so that decay can never fully suppress an entry that has no competitor:
w = max(0.05, exp(-ln(2) * age_days / half_life))
score = 0.55 * relevance + 0.25 * w + 0.20 * importanceThat three-term shape is not something I invented. The Generative Agents paper (Park et al., 2023) scores memories by summing normalized recency, importance, and relevance, with recency as an exponential decay over hours since last access. It is worth reading for the ablations alone: removing any single component degraded behavior measurably.
One honest note on framing. Exponential decay in a retrieval score resembles the Ebbinghaus forgetting curve, and it is tempting to cite that as justification. It is not one. Ebbinghaus measured human recall of nonsense syllables in 1885. The reason to use exponential decay here is that it is memoryless, has a single interpretable parameter, and never produces a cliff. Human memory is an analogy that helps explain the design to a colleague, not evidence that the design is correct.
In Unimatrix, half-life is a property of the memory class rather than a global setting, and durable identity facts are explicitly exempt from decay so they cannot age out from under you. The write path that carries the volatility hint is documented with the rest of the tool schemas in the MCP reference.
Your AI remembers everything. Everywhere.
Unimatrix gives you a shared, durable memory layer across Claude Desktop, Cursor, ChatGPT, and Gemini. Setup in 2 minutes. Free and paid plans available.
Keep reading
Self-consistency samples k reasoning paths and takes the majority answer. It works because errors scatter and correct answers converge, and it costs k times as much.
License terms, context length, and tool-calling reliability matter more than leaderboard rank. A filter for deciding which open weights deserve a GPU-hour.
An MCP client is a non-browser, long-lived consumer. That breaks the assumptions behind short-lived OAuth tokens, and the fix is scoped keys with rotation.