Short version: LangGraph's Store and Mem0 solve the same thing — long-term, cross-session agent memory, the tier where a fact from one conversation resurfaces in another. The difference the comparison tables miss is who decides what to remember. The Store is a primitive: it writes exactly what you tell it. Mem0 is a layer: it reads the conversation and extracts the facts for you. That one distinction drives cost, control, and lock-in — so decide on that, not on feature checklists.
| Build: LangGraph Store | Buy: Mem0 | |
|---|---|---|
| Who extracts | you | an LLM pass |
| Write | store.put(ns, key, val) | memory.add(msgs, user_id) |
| Data lives in | your Postgres | your DB or Mem0 cloud |
| License | MIT | Apache-2.0 |
Build: the Store writes exactly what you tell it#
LangGraph's long-term memory is a BaseStore — a namespaced key-value store with optional vector search built in (BaseStore source). You compile it alongside the checkpointer, then write and read inside your nodes:
from langgraph.store.memory import InMemoryStore
store = InMemoryStore(index={"embed": embed_fn, "dims": 1536})
graph = builder.compile(checkpointer=checkpointer, store=store)
# YOU decide what's worth keeping, and write it verbatim:
store.put(("users", user_id, "facts"), key="tz",
value={"text": "Prefers UTC; based in the EU."})
# Read it back by meaning, in any future thread:
store.search(("users", user_id, "facts"),
query="what timezone?", limit=3)
The defining property is right there in put(): nothing is inferred. The store holds the exact object you passed. That's the build cost — you write the "is this worth remembering?" logic yourself — and the build payoff: deterministic memory, a schema you control, and the data sitting in your own Postgres (swap InMemoryStore for the Postgres store in production). It's MIT-licensed and, if you're already on LangGraph, it's zero new infrastructure — the same box that runs your checkpointer runs this.
Buy: Mem0 decides what to remember for you#
Mem0 collapses the same tier into two calls, and the first one does the work you'd otherwise write yourself (Mem0 repo):
from mem0 import Memory
memory = Memory()
# add() runs an LLM pass that EXTRACTS the salient facts, then stores them:
memory.add(conversation_messages, user_id="alice")
memory.search(query="any dietary limits?",
filters={"user_id": "alice"}, top_k=3)
You hand add() raw messages; it returns having decided what mattered and saved that. For a team that just wants "memory that works," this is the appeal — you skip the extraction layer entirely, and it's framework-agnostic, so the same memory follows an agent whether it's built on LangGraph, a bare loop, or something else. It's Apache-2.0 and runs three ways: a library (pip install mem0ai), a self-hosted server, or a managed cloud.
Two things to price in before you lean on it. First, the extraction isn't free — every add() spends an LLM call on top of the embedding, so a chatty agent that calls add() each turn pays a per-write token tax the Store doesn't have. Reads and writes to memory already cost differently; Mem0 tilts the write side further. Second, the 2026 managed platform defaults to single-pass, ADD-only extraction — memories accumulate and nothing is overwritten. That's simple and fast, but if your domain has facts that supersede each other ("moved from Berlin to Lisbon"), accumulation is how a store slowly fills with contradictions, one of the ways agent memory rots in production. Needing a timeline is the signal to look at a temporal-graph layer instead — the Mem0 vs. Zep vs. Letta split turns on exactly this.
The decision, in one line each#
- Already on LangGraph, and you want control over what's stored and where? Use the Store. It's the native primitive, your data stays in your Postgres, and you're genuinely not missing much by not buying — you're trading a bit of extraction code for full determinism.
- Not on LangGraph, or you want fact-extraction handled and memory that travels across frameworks? Buy the layer. Mem0's two calls are a real shortcut, and being framework-agnostic is worth money if your stack isn't settled.
- The anti-pattern: bolting Mem0 onto a LangGraph app whose Store already does the job. Now you run two memory systems, write every fact twice, and get to keep them consistent forever. Pick one owner per tier.
If you're still deciding whether you need a long-term store at all — versus just retrieving from your documents at query time — that's the agent memory vs. RAG question, and it's worth answering before either of these. And if the answer is "one agent, one box, ship today," you may not need a service or a framework primitive: persistent memory in one SQLite file is the third door. Build, buy, or one file — decide on who extracts, not on the feature grid.



