Skip to content

When a newer memory contradicts an older one, what happens to the older one?

Buyers ask a practical question: "How do memory layers handle automatic consolidation and forgetting to prevent prompt context bloat?" Under that sentence sits one mechanical test you can put to every product, including ours. When a newer memory contradicts an older one, what happens to the older one? Not what gets retrieved. What happens to the thing that was true.

We build one of the six systems in this comparison, so read this the way you would read any vendor's comparison. Our row is the sixth answer, not the best one, and it is a correction of two earlier cuts: one presented a merge step as our answer, the next said the old record is never marked. Neither is right. The section about us comes last, with its limits stated first.

This page grew from three documentation sweeps. The first, on 2026-09-08, read one root page per vendor and called it a documentation tree. It missed Cognee's memory-graph page, on which consolidate, consolidation and their other forms appear eleven times, and it missed Mem0's Dream. The second, on 2026-09-10 and 2026-09-11, read every page named in the method note at the end and counted words. The third, on 2026-09-12, read the mechanisms on those pages with one instruction, refute each row, and it changed four rows of six: Supermemory, Cognee, Letta, and ours. The corrections share one cause. Counting pages, or words, is not reading mechanisms. No performance, latency, accuracy, or benchmark number appears anywhere in this article, for any system.

TL;DR

  • The question is mechanical. When a newer memory contradicts an older one, what happens to the older one? Six systems answer it, all six, in six different ways.
  • Marked invalid, kept, and the filtering is yours. Zep's ingestion invalidates the older fact rather than leaving conflicting truths side by side. The fact stays with an invalid_at stamp, and Zep's pages tell you to mark or filter it yourself. On two plans, derived observations go further: the older one is retired.
  • Replaced for search, kept for audit, and some of it expires. Supermemory keeps the old fact and stops returning it for search. The same page names automatic forgetting: temporary facts expire, episodes decay unless significant. Expired and forgotten memories leave search by default and can be asked back.
  • Both kept, three marks on offer, none on by default. Cognee can stamp the old node closed, tag the older edge superseded, or draw a contradicts edge. Each is a call or a flag you make. Retrieval is not filtered yet, so the current-state view is a filter you write.
  • Both kept, badged, the reader chooses. Mem0's Dream marks the older fact and returns both by default; latest_only=true asks for the current truth, per call.
  • Overwritten in place under a ceiling, with a background rewrite behind it. On Letta's memory blocks the last write wins inside chars_limit, and Letta now says not to build on blocks. Its harness runs Dreaming: background subagents rewrite memory files, every edit committed to git.
  • Kept, marked if the writer says so, not hidden yet. On our hosted service a write can name what it supersedes; the old record gains a pointer and still shows up in search, because the read-side filter is deployed and switched off. The merge endpoint responds 503.

How memory layers handle automatic consolidation and forgetting

Consolidation is a merge: folding several records into one, or rewriting an existing record with new evidence, so the store does not treat every version as equally current. The offline-phase framing sits under this page's mechanical question. Forgetting, in the buyer's wording, is whatever the product does so the prompt window stops filling with things already fixed.

None of the six answers below is an absence. Each product states a path, in its own words, on a named page. The paths differ. That is the point.

The same six systems appear in the paired question about whether anything changes when an outcome was bad. Here the subject is the old record itself.

What a store can do with an old record

A store has four options when a new fact collides with an old one. Take the old record out. Leave it in and stop returning it. Refuse more than a fixed amount in the first place. Fold several records into one.

Each option loses something. Taking it out loses the history: knowing a decision was reversed is different from never having made it. Leaving it in costs storage and search. A fixed cap is predictable and blunt. Folding records is the most work and the hardest to explain.

Three checks run on a vendor's own pages, without a demo call:

  1. Is the old record removed, hidden, or kept?
  2. Who decides: a rule, a model, a size, or you?
  3. Is the decision visible from outside?

The rest of this article is those three checks, applied to six published answers.

How Zep consolidates observations

Zep's answer has two layers, and the earlier cut of this page showed only the second.

At the fact level the answer is invalidation. Invalidation is stamping the older fact with the time it stopped being true, and keeping it. On how graph creation works, Zep writes: "Each extracted fact is compared to existing edges: duplicates merge, and contradictions invalidate older facts rather than leaving conflicting truths side by side". The decision is a model's, at write time, and the facts page hedges it: "Zep attempts to invalidate the fact". The mark outlives the episode that made it: "If an episode invalidates a fact, and the episode is deleted, the fact will remain marked as invalidated" (deleting data from the graph).

What the mark does at read time is only half stated. No page in the sweep gives the default read rule outright. A changelog entry of 2026-08-11 treats a stale result as a defect and fixes its cause: before the fix, "a later value never superseded the earlier one and search kept returning the stale fact". So Zep reads supersession as something search honours. The context block guide still tells you, when you build your own block, to "clearly mark any fact with a non-null invalid_at as no longer valid", and the search page shows the filter on invalid_at for facts that are still valid. The mark is the store's; relying on it alone is not what the guide recommends.

Observations are the second layer, and the one that retires. On the observations page, Zep writes that "Observations are deduplicated and merged", that "the existing observation is regenerated with the new evidence merged in", and that "the older observation is retired so the graph reflects the current state of what is known". Observations are derived from the graph, "Observations are read-only", and the page opens with the gate: "Available to Flex Plus and Enterprise customers". Whether retired means hidden or deleted, the page does not say.

So the fact that was true stays, marked. On two plans, the summary built over it is rewritten when new evidence fits it, and retired when a newer summary supersedes it. The history of the reversal survives at the fact level, where the stamp is documented. At the observation level the page says the older observation is retired and does not say what retired leaves behind, so what a reader can check ends there.

How Supermemory handles contradicting facts

Supermemory's graph-memory page puts the claim under the subtitle "temporal truth, and automatic forgetting". The page says: "New fact replaces what was true before for search purposes; history can remain for audit". It also says the product can "keep retrieval on the current fact without erasing the past".

The old fact is not taken out. It stops being what you find. Search moves to the new fact; audit can still see the old one. The decision is the product's, made as the memory is written and in the dreaming pass the page describes, not yours. The caller's lever on that page's neighbours, the review queue for inferred memories, is a different object, covered in the paired article.

The second half of the subtitle is where the earlier cut of this page stopped short. The same page names automatic forgetting in its own words: "temporary facts drop after they expire", and in the table of memory types, episodes "Decays unless significant" while preferences "Strengthens with repetition". The search page states the read-time rule: "By default, search excludes memories that have been forgotten or have passed their forgetAfter expiration", and shows how to ask for them back: "Set include.forgottenMemories to true to recover them".

What that does to the stored record is stated for one case and not the other. An explicit forget is "excluded from search results but preserved in the database" (memory operations). For an expired fact the pages say what leaves search and nothing about storage. So the reachable set shrinks, on contradiction and on a timer. Whether the store shrinks is not on the page.

Cognee: three marks, none on by default, and a filter you write

Cognee keeps both records. What the earlier cut of this page got wrong is who marks the older one and who filters it. On Cognee's pages, both are you.

Three marks are on offer. The fact validity guide stamps a node closed, by a call you make: "Supersede instead of delete: the old node stays in the graph with valid_to set". The same guide limits where the stamp lands: "Only the default Ladybug store implements update_node today". The changelog describes temporal contradiction resolution for relationships you name as functional: the older assertion is tagged superseded, "nothing is deleted and provenance is preserved", and the parameter that turns it on defaults to None, so the default pipeline does not do it. The cognify page lists the third: "Detect contradictions (opt-in, off by default)", a model judging pairs and recording a contradicts edge.

Then the sentence the earlier cut missed, on the fact validity guide: "Retrieval is not filtered yet." In full: "Search and graph completion neither filter nor down-weight closed nodes, so a superseded fact can still surface in results". The walkthrough on Memory graph for AI agents says the same from the other side: "current-state filtering is policy", and "a current-state view is a one-line filter on the superseded property". Its promise that "Historical states can still support retrospective queries, while superseded claims can be excluded from current-state retrieval" is a capability. They can be excluded, by the line you write.

Two pages in this sweep name the cost of a wrong merge. Zep's graph creation page says "A wrong merge corrupts identity in ways that are hard to undo" and prefers under-merge: "better to leave two nodes than to fuse the wrong ones". Cognee's walkthrough says where the cost lands: "an incorrect merge connects records that belong to different entities, so getting this wrong comes with a cost". A wrong merge does not produce a smaller store. It produces a wrong one. Their instruction follows from that cost: "Automate merges only under a defined confidence policy". The deduplication article on this site is the longer reading of what a wrong merge costs, across six systems at pinned commits. That article read Cognee's source at a pinned commit and found an entity description overwritten when two names collide. That is entity resolution on a name, a different operation from a contradicting fact, which the pages above mark rather than overwrite. Both can be true.

So: both kept; marked at write time if you turned a mark on; filtered at read time if you wrote the filter. Of the six, this is the answer that hands you the most and decides nothing at read time.

Does Mem0 delete superseded memories?

No. This is a correction the article owes.

An earlier cut of this comparison said Mem0 had no path for the old record. That came from a sweep that read one page of their documentation and called it complete. Their page on memory operations does say "add memories through an additive pipeline". That phrase is real. It describes how a memory is written, which is a different question from what happens to the one it contradicts. Reading the first as an answer to the second was the mistake, ours not theirs.

Dream is the path. It is a feature of the Mem0 platform, made of three actions: Supersede, Merge, and Synthesis. The page's opening line is: "Dream keeps a user’s memory clean over time by distilling recurring patterns, retiring outdated facts, and merging duplicates in the background".

Supersession, in Mem0's table, is this: "Marks an older fact as outdated when a newer one contradicts it". The page adds that "Supersede runs automatically as part of adding memories, on every plan", that "Superseded memories are not deleted and not hidden by default", and that "Nothing Dream does is destructive".

Supersede and Merge are "Always on, all plans". Synthesis is opt-in, Pro and above, toggled per project.

Reads decide what you see. A normal search or get returns superseded memories alongside active ones, badged as superseded. latest_only=true returns only the current truth. Merged duplicates are hidden from reads by default and surfaced with include_merged=true.

The older record is not taken out and not hidden. A normal read returns both, the old one badged. The reader asks for only the current truth per call. The version you get is decided by whoever is reading, every time, not once by the store. Mem0 also lets the caller put a date on a memory: on the expiration page, "Expiration hides a memory, it does not delete it."

An earlier article on this site, on deduplication, describes Mem0's open-source add() path as leaving both facts untouched. Dream is a platform feature documented on the platform pages. The two statements are about different surfaces, and both can be true.

Letta: overwritten under a ceiling, with a background rewrite behind it

Letta's answer depends on which Letta you read, and the earlier cut of this page read the older one.

On memory blocks, the block carries its ceiling in metadata, chars_limit=5000 in the page's example, and the old text does not survive a rewrite: "If multiple processes (agents or external scripts) modify the same block concurrently, the last write wins and overwrites all earlier changes". Their instruction: "Ensure your application logic accounts for full replacements, not merges". Hitting the ceiling has three remedies on the shared memory page: raise the limit, archive old content to a separate block, or "Have an agent periodically summarize". The ceiling is predictable. What stays under it is the agent's decision, written over what was there. No page gives a block a version history, so an overwritten value is gone unless the file-backed memory described below is on. The v1 API has a background pass of its own, a flag on agent creation whose whole description is one line: "If set to True, memory management will move to a background agent thread."

The same shared memory page carries a sentence that changes what the ceiling is worth: "Memory blocks may be deprecated in the future. We do not recommend building on memory blocks anymore."

The Letta its pages now point to keeps memory as files in a git repository. On MemFS: "Every memory edit is committed to the MemFS git repository. This provides version history, conflict resolution, and a clear boundary between saved memory and uncommitted changes". It is on by default in the Agent SDK and, on a self-hosted server, "MemFS is opt-in per agent." (Docker page). The consolidation step there is called Dreaming, a word Mem0 and Supermemory also use, each for its own mechanism. On the Agent SDK memory page: "Dreaming uses background subagents to review recent conversations, consolidate lessons, and update memory without interrupting active work". It runs off, on a step count, or on a compaction event, and at the trigger it can "remind the agent to update memory, or automatically launch a background dreaming subagent". The memory configuration page says of its optional review pass that it "does not ask you for approval". The older version of a memory file survives as a commit.

Conversation history is a third layer with a third answer: compaction summarises part of the context, and "The Letta API stores all messages, so even after a compaction / eviction" the old messages remain retrievable (stateful agents).

So: on blocks, overwritten, with the ceiling stated in advance and no history unless the git-backed memory is on. On MemFS, rewritten in the background by a model, with every prior version in git. Two Lettas, and the page you land on decides which you get.

Does Mnemoverse consolidate memories?

Not on the hosted service. This row is a correction, twice over.

An earlier cut presented our merge step as our answer. It is not. The API reference entry for POST /memory/consolidate opens with: "Consolidation is off on the hosted service and we do not currently recommend turning it on." Next: "The endpoint responds 503 with a typed reason rather than consolidating." The API overview gives both reasons in one sentence: "consolidation exists in the engine but is switched off on the hosted service, because it has never once completed in production and a prototype competes with its own sources for the same result slots". The same page: "Memories are kept rather than compressed away".

The next cut said that both records stay and neither is marked. The second half is wrong. A write can name the records it replaces, in a field called supersedes, and the reference says what happens to each of them: it "gains a superseded_by pointer to the new atom and stays fetchable by ID". That is a mark, made by the writer, at write time. What the mark does not do yet is hide anything. The reference is direct: "It records the correction; it does not yet hide the original." The filter that would do the hiding exists, under a callout titled "Read-side filtering is deployed, and switched off (as of 2026-08-29)", and "No response field reports whether the server-side filter is on, either." The agent-facing tools do not carry the field: "No MCP tool in this package exposes it yet" (MCP server).

Nothing expires. On the same MCP server page: "nothing about a stored memory decays over time or is deleted by age", and outcome feedback re-ranks rather than removes: "an unhelpful memory is out-ranked, never erased". Every revision counts against the plan's atom limit, in the reference entry for the stats call: "a supersession chain of five revisions counts as five".

So on the hosted service: both records stay; the older one is marked if the writer says so; a default read still returns it; nothing is merged, and nothing leaves. That is a real answer to losing the record of a decision you reversed. It is no answer to a store that keeps growing, and the atom limit is where you will feel it. The engine is closed; what you can read is the reference and its reasons. The Hebbian write-up records the same fact: consolidation is switched off on the hosted service.

We are the sixth answer here, not a special case and not a ranking.

Six answers, one axis, and what to ask a vendor

Six answers to one question. Marked invalid and kept, with the filtering yours (Zep). Replaced for search, kept for audit, some of it expiring (Supermemory). Both kept, marked if you turn a mark on, filtered if you write the filter (Cognee). Both kept, badged, the reader picks per call (Mem0). Overwritten under a ceiling, or rewritten in the background with git behind it (Letta). Kept, marked if the writer says so, not hidden yet (ours).

None is wrong. They answer different fears.

A wrong answer confidently repeated: what matters is the default read, not the mark. On the pages read here, two stop returning the old record without being asked. Supermemory, whose search moves to the new fact, and Letta's block, where the old text is gone. Zep marks and tells you to filter. Mem0 badges and returns both. Cognee marks only if asked and filters nothing yet. We mark only if asked and hide nothing yet.

A store and a bill growing forever: Supermemory names expiry and decay and says what leaves search. Mem0 lets the caller set an expiration date that hides without deleting. Letta caps the block. Zep's FAQ says "Zep does not configure a fixed graph-size limit". Cognee and we state no age rule for stored facts, and our plan limit counts every revision.

Unpredictable context cost: two pages state a ceiling before anything runs. Letta's block carries its chars_limit in the record's own metadata; Cognee caps the preference node's injected text at 2000 characters, oldest lines first out (user preferences). Neither bounds what retrieval adds on top.

Losing the record of a reversed decision: five of the six keep it and mark it, two of them only when asked (Cognee, ours). Letta's block is the exception, last write wins. Its MemFS keeps every version in git.

The axis a feature list does not show is when the decision happens, and whose it is. Zep and Supermemory decide at write time, by a model. Mem0 marks at write time and lets the reader decide per call. Cognee and we mark at write time only when the caller asks, and leave the reader to filter: Cognee because retrieval is not filtered yet, we because the filter is switched off. Letta's block decides at write time, by whichever agent wrote last; its Dreaming decides in the background. A write-time decision is a rule you inspect in the store. A read-time decision is a parameter you pass on every call, and a default you can get wrong. A decision that is nobody's yet is the third case, and two of the six are in it.

The vendor question becomes three, none of them "does it have memory": what happens to the old record; who decides; can you see it from outside. The third is where four of the six, ours included, stop being checkable. The mechanism is described on a hosted product's pages (Mem0's Dream, Zep's ingestion and observations, Supermemory's graph memory, ours), and you are reading a description of a thing rather than the thing. Cognee and Letta publish source you can read, and Zep publishes Graphiti, the engine under its hosted layer. This article is a reading of what is published, and says so.

SystemOld recordWho decidesWhenVisible from outside
ZepKept, stamped invalid_at; on two plans, observations retiredA model at ingestion; you at readWrite time; the read is yoursHosted documentation; Graphiti source for the engine
SupermemoryReplaced for search, kept for audit; temporary facts expireThe system's model, in dreamingWrite time and a background passHosted documentation
CogneeBoth kept; three marks, each opt-in; retrieval not filtered yetYou: the mark and the filterWrite time for the mark, read time for the filterPublished source
Mem0 (Dream)Both kept, old fact badged; reader chooses per callThe store marks, the reader choosesWrite time, then every readHosted documentation
LettaBlock overwritten under a ceiling; MemFS files rewritten by Dreaming, prior versions in gitThe agent that wrote last; background subagentsWrite time; backgroundPublished source
MnemoverseBoth kept; marked when the writer names it; not hidden; merge refusedThe writer; the hiding is nobody's yetWrite time; read-side filter offHosted documentation

The table is a reading of published pages. It is not a benchmark, and it is not a claim about behaviour beyond those pages.

The one-minute test for agent memory consolidation

Run this on the tool you already use. Tell it something. Tell it the opposite a week later. Ask a question that touches both. Ask a second question about what you used to think.

First answer current and second finds nothing: the old record was taken out, or written over.

Both come back: nothing was marked, or the mark does nothing at read time.

First current and the second still finds the old one: you are in the middle of this article, where most of them are.

That last outcome is Zep's stamp and Mem0's badge. Supermemory reaches it only through the audit path, which is not the default read. Cognee and we sit in "both come back" until the caller filters: Cognee because retrieval is not filtered yet, we because the read-side filter is switched off, so on our hosted service the first answer is current only if your client honours superseded_by on the REST read item, and the MCP tools do not expose the pointer yet. Distinguishing these outcomes takes the three checks, not the first reply.

Common questions

How do memory layers handle automatic consolidation and forgetting?

They do not share one mechanism. Put to six products, the question becomes: when a newer memory contradicts an older one, what happens to the older one? Zep marks the older fact invalid and keeps it, and on two plans retires derived observations. Supermemory replaces the old fact for search, keeps history for audit, and lets temporary facts expire. Cognee keeps both and offers three ways to mark the older one, none on by default, with the filter left to the reader. Mem0 keeps both, badges the older one, and lets the reader choose per call. Letta overwrites the memory block in place under a character ceiling, and its newer harness rewrites memory files in a background pass with git history behind it. Mnemoverse keeps both, marks the older one only when the writer says so, and does not yet hide it.

What happens to old memories when an AI agent learns a new fact?

The store can take the old record out, leave it in and stop returning it, refuse more than a fixed amount, or fold records into one. Each loses something: taking it out loses the history, leaving it in costs storage and search, a cap is blunt, and folding is the hardest to explain. Run three checks on the vendor's pages: is the old record removed, hidden, or kept; who decides (a rule, a model, a size, or you); and whether the decision is visible from outside.

Does Mem0 delete superseded memories?

No. On the Mem0 platform, Dream's Supersede marks an older fact as outdated when a newer one contradicts it. Supersede runs automatically as part of adding memories, on every plan. Superseded memories are not deleted and not hidden by default. Nothing Dream does is destructive. A normal read returns both, the old one badged; latest_only=true returns only the current truth.

How does Zep consolidate observations?

At the fact level, Zep's ingestion compares each extracted fact to existing edges: duplicates merge, and contradictions invalidate older facts rather than leaving conflicting truths side by side. The older fact stays, stamped invalid_at, and Zep's pages tell you to mark or filter invalidated facts yourself. Observations, a derived layer available to Flex Plus and Enterprise customers, go further: when new evidence fits an existing observation, that observation is regenerated with the new evidence merged in; when a newer observation supersedes an older one, the older observation is retired so the graph reflects the current state of what is known.

How does Supermemory handle contradicting facts?

Under the subtitle temporal truth, and automatic forgetting, Supermemory's graph-memory page says a new fact replaces what was true before for search purposes; history can remain for audit. The same page says temporary facts drop after they expire and that episodes decay unless significant. By default, search excludes memories that have been forgotten or have passed their forgetAfter expiration, and the search page shows how to recover them. The old fact stops being what you find; a forgotten one is preserved in the database.

Does Mnemoverse consolidate memories?

Not on the hosted service. The API reference says consolidation is off on the hosted service and we do not currently recommend turning it on; the endpoint responds 503 with a typed reason rather than consolidating. What exists instead is explicit supersession: a write can name the records it replaces, and each gains a superseded_by pointer and stays fetchable. The read-side filter that would hide superseded records is deployed and switched off as of 2026-08-29, so a superseded record still shows up in search results.


Live probes for this article were run on 2026-09-11 and 2026-09-12 with full browser headers, a control address on every host, and every named page answering 200, continuing a sweep that began on 2026-09-10. Pages read: Mem0 https://docs.mem0.ai/llms-full.txt (full export), https://docs.mem0.ai/platform/features/dream, https://docs.mem0.ai/platform/features/memory-expiration and https://docs.mem0.ai/core-concepts/memory-operations; Cognee https://docs.cognee.ai/llms-full.txt (full export), among its pages https://docs.cognee.ai/guides/fact-validity, https://docs.cognee.ai/changelog, https://docs.cognee.ai/core-concepts/further-concepts/user-preferences and https://docs.cognee.ai/core-concepts/main-operations/legacy-operations/cognify, and https://www.cognee.ai/memory-graph-for-ai-agents; Supermemory https://supermemory.ai/docs/llms-full.txt (full export), https://supermemory.ai/llms.txt, https://supermemory.ai/docs/concepts/graph-memory.md, https://supermemory.ai/docs/recall/search and https://supermemory.ai/docs/recall/memory-operations; Letta, all 632 pages listed in https://docs.letta.com/sitemap-0.xml, read as HTML with tags stripped, among them https://docs.letta.com/guides/agents/memory-blocks, https://docs.letta.com/v1-sdk/memory/shared-memory/, https://docs.letta.com/concepts/memfs/, https://docs.letta.com/agent-sdk/memory/, https://docs.letta.com/agent-sdk/reference/, https://docs.letta.com/configuration/memory/ and https://docs.letta.com/v1-sdk/concepts/stateful-agents/; Zep, all 324 pages listed in https://help.getzep.com/sitemap.xml, among them https://help.getzep.com/observations.md, https://help.getzep.com/how-graph-creation-works, https://help.getzep.com/facts, https://help.getzep.com/deleting-data-from-the-graph, https://help.getzep.com/advanced-context-block-construction, https://help.getzep.com/searching-the-graph and https://help.getzep.com/faq; Mnemoverse https://mnemoverse.com/docs/llms-full.txt, https://mnemoverse.com/docs/llms.txt, https://mnemoverse.com/docs/api/reference, https://mnemoverse.com/docs/api/overview and https://mnemoverse.com/docs/api/mcp-server. Quotations are contiguous substrings of the rendered text of the page named beside them (tags stripped, entities decoded, markdown flattened), not of the raw markup. Vendor punctuation, capitalisation, and emphasis inside quotation marks are the vendor's own. Where this article says a page is the only one to state something, it means the only one among the pages listed here. Not covered: the chat communities Mem0 and Supermemory run, which cannot be read from outside. Disclosure: this site publishes one of the six systems compared, our row is the last, it is a correction of our own earlier readings, and our limits are named before anybody else's. No performance, latency, accuracy, or benchmark number appears anywhere, for any system.

Edward Izgorodin · Mnemoverse · 2026-09-12

Mnemoverse is a persistent-memory API for AI agents. Free key: console.mnemoverse.com · Plans and limits · Docs: Getting Started