Skip to main content

Memory Expiration

Some facts are only true for a while. A trial plan ends, a seasonal preference goes stale, a support ticket ages past its retention window. Set an expiration_date on a memory and Mem0 stops surfacing it once that date passes, so you don’t need a cleanup job hunting for rows to delete. Expiration hides a memory, it does not delete it. The record stays in storage untouched. search() and get_all() skip it, fetching it by ID still returns it, and clearing the date brings it straight back.

How it works

  • Format: a plain YYYY-MM-DD date. No time component, no timezone offset.
  • Evaluated in UTC, never against the caller’s local timezone.
  • Inclusive of the date itself: a memory set to expire on 2030-01-31 stays visible all through 2030-01-31 UTC and disappears on 2030-02-01.
  • Only list-shaped reads filter: search() and get_all() (getAll() in TypeScript) hide expired memories. get(memory_id) always returns the memory, so there is no show_expired parameter on that path.
  • No expiration date means never expires. That is the default for every memory.
  • Malformed dates fail open: a stored value Mem0 can’t parse is treated as not expired. A bad date never makes a memory silently vanish.

Set an expiration date

Set it when you add the memory:
Or attach it to a memory that already exists, using update():
Full field lists live in the Add Memories and Update Memory references.

Read expired memories back

Pass show_expired (showExpired in TypeScript) to include them. It defaults to false on every client.
The same parameter and spelling work on the OSS Memory class. See Search Memories and Get Memories.
Expired memories are dropped before your top_k is applied, so Mem0 widens the internal candidate pool first and short result sets are rare. They are not impossible: if nearly every memory in a scope has expired, a call can still return fewer than top_k results. Pass show_expired: true to get the full set back.

Clear an expiration date

Pass an explicit None (Python) or null (TypeScript) to make the memory permanent again. The SDKs deliberately preserve that null instead of treating it as “argument not supplied”.
update() needs at least one of text, metadata, or expiration_date, and raises if you pass none of them. Clearing the date satisfies that on its own: the memory’s content and metadata are left alone.

What each client accepts

Reading the field back

Most clients return expiration as a top-level field on the memory: expiration_date in Python (Platform and OSS) and in the REST API, expirationDate in the Platform TypeScript SDK.
The OSS TypeScript SDK is the one exception. There, expiration round-trips under result.metadata.expiration_date, not result.expirationDate, on both get() and getAll().

Expiration, decay, and delete

These three get conflated. They solve different problems: Reach for Memory Decay when old memories should rank lower but stay searchable, expiration when a memory should stop appearing after a specific known date, and Delete when it should be gone for good.

Common patterns

Trial and subscription facts. “Alice is on the Pro trial” is true until the trial ends. Set expiration_date to that end date when you write the fact. If she upgrades, clear the date and the memory becomes permanent. If she doesn’t, it stops surfacing the next day on its own. Seasonal preferences. “Alex wants gift ideas for the holidays” matters in December and is noise in July. A short-lived expiration date keeps it from competing with evergreen preferences in every search. Retention windows. Data-retention policies usually want a soft window before a hard delete: keep a ticket’s memories searchable for 90 days, stop surfacing them, purge them later on a schedule. Expiration is the soft step, and a scheduled delete is the permanent one.

Memory Decay

Delete Memories