Blog·Learning

LangGraph memory: checkpointers, stores and long-term memory

By Shardul Mane·6 min read

A blurred photo of sunlight through leaves against a blue sky, with the supermemory logo and the headline LangGraph memory across threads.

LangGraph has two kinds of memory. A checkpointer saves a thread's graph state at every step, which gives you short-term memory, resumable runs and recovery from failures. A store saves data outside the graph state that any thread can read, which gives you long-term memory such as a user's preferences (LangGraph docs).

Most applications use both. An external memory service such as supermemory can take the store's place when you want facts pulled out of conversations, kept current and searched for you. Everything below was checked against LangGraph's docs on October 16, 2026, when langgraph 1.2.15 was current.

Checkpointer vs store: what's the difference?

Checkpointer Store
What it saves Snapshots of the graph state Data your app chooses, as JSON documents under a namespace and key
Scope One thread Every thread
What it gives you Conversation continuity, human-in-the-loop, time travel, recovery after a failure User preferences, facts and shared knowledge
How you use it Pass a thread_id in the config Read and write it from nodes through runtime.store

A new thread starts with empty state, so anything the user should find again in their next conversation has to come from the store, or from a memory service, not from the checkpointer.

How do you share memory across threads in LangGraph?

Compile the graph with both, and pass the user's identity in as context for each run. This example needs no model or network, so you can run it as a test:

from dataclasses import dataclass
from typing import TypedDict

from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.runtime import Runtime
from langgraph.store.memory import InMemoryStore


@dataclass
class Context:
    user_id: str  # resolved from your auth for each request


class State(TypedDict):
    answer: str


def recall(state: State, runtime: Runtime[Context]):
    item = runtime.store.get((runtime.context.user_id, "preferences"), "timezone")
    return {"answer": item.value["value"] if item else "unknown"}


store = InMemoryStore()
store.put(("user-a", "preferences"), "timezone", {"value": "Europe/London"})

builder = StateGraph(State, context_schema=Context)
builder.add_node("recall", recall)
builder.add_edge(START, "recall")
builder.add_edge("recall", END)
app = builder.compile(checkpointer=InMemorySaver(), store=store)

first = app.invoke({}, {"configurable": {"thread_id": "thread-1"}}, context=Context(user_id="user-a"))
second = app.invoke({}, {"configurable": {"thread_id": "thread-2"}}, context=Context(user_id="user-a"))
other = app.invoke({}, {"configurable": {"thread_id": "thread-3"}}, context=Context(user_id="user-b"))
assert first["answer"] == second["answer"] == "Europe/London"
assert other["answer"] == "unknown"

Two threads for the same user find the preference, and a third user doesn't. Reading the store and the user through the Runtime object, the way LangGraph's memory docs recommend, keeps one request's user from leaking into another's, which a global variable can't promise once requests run side by side.

Both backends here live in memory, so they show thread and user scope inside one process, not persistence after a restart. InMemorySaver loses everything when the process stops. In production, use database-backed versions such as PostgresSaver and PostgresStore (persistence docs).

How do you add supermemory to a LangGraph agent?

A store keeps exactly what you put in it. supermemory takes the conversation itself, pulls out the facts, keeps them current when they change, builds a profile for each user, and returns what's relevant to the next question (how it works). In a graph, that's two nodes around the model: recall before it answers, save after. This follows the LangGraph integration docs for the v5 SDK:

from dataclasses import dataclass
from typing import Annotated, TypedDict

from langchain_core.messages import SystemMessage
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.runtime import Runtime
from supermemory import Supermemory  # pip install supermemory (v5 SDK, 5.0.0 or later)

llm = ChatOpenAI(model="gpt-5.5")
memory = Supermemory()  # reads SUPERMEMORY_API_KEY


@dataclass
class Context:
    user_id: str    # the namespace: one per user
    thread_id: str  # one supermemory document per conversation


class State(TypedDict):
    messages: Annotated[list, add_messages]
    memory_context: str


def recall(state: State, runtime: Runtime[Context]):
    user = runtime.context.user_id
    query = state["messages"][-1].content
    profile = memory.profile(user).profile
    found = memory.search(user, query=query, search_mode="memories", limit=5).results
    facts = [m.memory for m in profile.static + profile.dynamic] + [r.memory for r in found if r.memory]
    return {"memory_context": "\n".join(f"- {f}" for f in facts)}


def respond(state: State):
    system = SystemMessage(content=f"You are a helpful assistant. What you know about this user:\n{state['memory_context']}")
    return {"messages": [llm.invoke([system] + state["messages"])]}


def save(state: State, runtime: Runtime[Context]):
    turn = f"user: {state['messages'][-2].content}\nassistant: {state['messages'][-1].content}"
    memory.add(runtime.context.user_id, content=turn, id=runtime.context.thread_id)
    return {}


builder = StateGraph(State, context_schema=Context)
builder.add_node("recall", recall)
builder.add_node("respond", respond)
builder.add_node("save", save)
builder.add_edge(START, "recall")
builder.add_edge("recall", "respond")
builder.add_edge("respond", "save")
builder.add_edge("save", END)
app = builder.compile(checkpointer=InMemorySaver())

app.invoke(
    {"messages": [{"role": "user", "content": "Plan my week around the launch"}]},
    {"configurable": {"thread_id": "chat_42"}},
    context=Context(user_id="user_123", thread_id="chat_42"),
)

The checkpointer still owns the thread: this conversation's messages and where the graph got to. supermemory owns what should outlive the thread. A new thread for user_123 starts with empty state, and the recall node fills in what that user told you before. Get an API key from the supermemory console, and see pricing for what saves and searches cost.

Keep these as visible stages in the graph, so each one can be tested and logged on its own:

Stage What it should do
Resolve identity Get an authorized user or tenant from your auth, before the graph runs
Recall Fetch a bounded amount of relevant background
Answer Combine the current messages with the recalled facts, marked as background
Save Store only what your retention policy allows
Observe Record IDs, status and timing, without logging sensitive content

Why does the save need a stable ID?

A checkpoint records how far the graph got. A write to supermemory is a separate side effect, and the two don't commit together. If a run fails after the save node sends its write but before the next checkpoint lands, resuming the thread can run the save again.

That's why the save uses the thread ID as the document id. In the v5 API, sending content again with the same id adds to or diffs that document instead of creating a copy, and unchanged content isn't billed twice (v5 guide, billing docs). Derive IDs from the source action, never from a random value generated on each retry, and keep the ID supermemory returns so a later correction or deletion reaches the right record.

When should writes wait, and when can they run in the background?

New memories form in the background after a save returns, so a new namespace can look empty at first (v5 guide). Plan for that gap instead of fighting it:

  • If the next node needs a fact from this turn, carry it in the thread state instead of searching supermemory for something that may not have formed yet.
  • If the next request needs it, save with dreaming="instant", which processes each document right away, for one extra operation per document.
  • For everything else, let processing run in the background, and don't make every step wait for ingestion.
  • Treat "not found yet" differently from "doesn't exist". Check the document's system.dreamingStatus rather than reading an empty search as a permanent answer.

For background writes, use a queue that survives a worker restart and tells retryable service failures apart from invalid input. The ingestion guide covers freshness and retries in more depth.

What should you test before production?

Run these against your real checkpointer, store and memory service, not the in-memory ones:

  1. A restart. Stop the process, reconnect to the configured backend, and resume a known thread. Check message order, tool results and the next scheduled step.
  2. A replay around the write. Stop the run just before the save, just after it, and after the next checkpoint. The application should tell work that never happened apart from work whose acknowledgment was lost, and no case should create a duplicate.
  3. Shared memory across threads. Use two threads for one fictional user and a third for another user. Shared context should reach only the first two.
  4. A correction. Correct the shared fact, then resume an old thread, and check the old checkpoint's context doesn't win over the new memory.
  5. A deletion. Delete the source and confirm the fact no longer comes back.

Measure recall and latency with your own model, checkpointer, data and expected load. The memory debugging guide helps when one of these fails, and the isolation guide covers keeping tenants apart.

Common questions

Does LangGraph have long-term memory?

Yes. Stores are LangGraph's long-term memory: they hold data across threads under namespaces such as a user ID, and you read and write them from nodes. A memory service such as supermemory is the other option, when you want facts extracted and kept current for you.

What's the difference between a checkpointer and a store?

A checkpointer saves one thread's graph state, so a conversation can continue or recover. A store saves data that every thread can read, such as a user's preferences.

Does MemorySaver persist between restarts?

No. MemorySaver and InMemorySaver keep checkpoints in RAM, so a restart loses them. Use a persistent checkpointer such as PostgresSaver, or SqliteSaver for local development.

Can I use supermemory with a LangChain agent instead of a graph?

Yes. The LangChain memory guide shows the same recall-and-save pattern with create_agent middleware. For the same loop without a framework, see the quickstart.

  1. We dug into Claude Code's memory. Here's exactly how it worksLast month, our founder Dhravya Shah broke down how Instinct's memory works. We wanted to do the same for Claude, since that's where we spend most of our day.
  2. How AI memory actually works. A beginner's guideHow AI apps remember things between chats, why a bigger context window doesn't solve it, and the parts every memory system shares.
  3. We're open sourcing the company brain. Here's how we designed the multiplayer harnessCompany Brain is now open source. A walkthrough of the multiplayer harness behind its Slack experience, from proactivity and memory boundaries to approvals and recovery.
  4. Jev changes a lot in memory & context engineering. Here's exactly how.We tested Jev across reranking, chunking, observation, and harness decisions. Here is where fast decision models help memory systems, where they cost more, and where they still fall short.
  5. I reverse-engineered Instinct's memory. Here's exactly how it worksInstinct keeps its memory as git-tracked markdown files, found with grep rather than vectors. Here is the whole system as far as black-box probing can reconstruct it, and how to rebuild it on supermemory in about 60 lines.
  6. An update to supermemoryWe've discontinued the supermemory company brain and Nova. Everyone who was charged has been refunded, our MCP and plugins continue to run, and we're going all in on the memory engine.
  7. Scaling Conversations: How Adapta Grew Usage Without Losing ContextAdapta added Supermemory as a persistent memory layer so every conversation keeps its context — letting the team scale usage without losing the thread.
  8. How Chatarmin Ditched RAG and Went Memory-Only with SupermemoryChatarmin replaced a heavy RAG pipeline with Supermemory's memory layer — cutting average AI response time from 40s to 12s and token usage by 40–50%.
  9. SMFS: making agentic retrieval 55% cheaper AND more accurateWe launched SMFS.ai (Supermemory Filesystem) a few weeks ago, with a simple bet: We can redesign the filesystem specifically for agents, with special files, structures, and commands that it can use for it's tasks. Today, SMFS is used by hundreds of companies to power their agents.
  10. Introducing Dynamic Dreaming: supermemory now connects the dots, for you.Dreaming is magical. TLDR: We're launching Dynamic Dreaming in supermemory today, which automatically works if you're using supermemory in any way - API, OpenClaw, Hermes agent, etc.
  11. Dear reader, we just made supermemory insanely cheap... the Context CloudWhen I first started building supermemory, I had one goal: To build the best memory system for AI. I would talk to customers, and find out that memory was not the only thing they needed - They were all setting up 7-8 different vendors at the same time.
  12. Introducing @supermemory/tools v2.0.0Today we're releasing v2.0.0. This release unifies the API across all agents sdk integrations from AI SDK to Mastra, makes conversation identity a first-class concept, and ships with memory saving on by default.
  13. Solving the Precision-Recall Tradeoff: Search Result AggregationWhen you're building memory for AI, search is your foundational layer. The way search generally works is straightforward: the user defines a query, and then sets a limit (top-K) on how many search results they want returned. Usually, this is set to 10 or 20.
  14. OpenClaw Memory Problems: Why It Forgets and How to Fix It (2026)OpenClaw remembers by writing Markdown files in its workspace, so it forgets anything the agent didn't save. Why that breaks down, how the supermemory plugin recalls and saves on every turn instead, and how to install it, free on every plan.
  15. Stateful Coding Agents with Memory: Build Long-Running Agents (2026)We built a plugin for Claude Code and OpenCode that gives your coding agent persistent memory. It remembers your preferences, learns your codebase, and never loses context mid-conversation. The result is an agent you can run for months without starting over.
  16. Clawd / Molt bot's memory SUCKS. We gave it supermemory.I'm the founder of supermemory. Clawd/Molt bot is blowing up right now, with many, many use cases. I set it up, too, and have been using it through telegram. TLDR: just go to https://supermemory.ai/docs/integrations/clawdbot to set up supermemory for your clawd bot.
  17. Catch up with our UNFORGETTABLE Launch WeekOver the last year, one belief has guided almost everything we’ve built at Supermemory AI becomes meaningfully useful only when it remembers. Memory shouldn’t be something developers rebuild from scratch. It shouldn’t be fragile, expensive, or trapped inside a single tool.
  18. Empowering the Next Generation of Founders: Supermemory Startup ProgramIf there’s one thing we’ve learned while building Supermemory, it’s that most startups don’t fail because they didn't build features; they fail when infrastructure slows them down, or they built too slow.
  19. Building code-chunk: AST Aware Code ChunkingAt Supermemory, we're building context engineering infrastructure for AI. A huge part of that is dealing with code: ingesting repos, understanding structure, and making it searchable. The problem is that most code chunking solutions are terrible. We built code-chunk to fix this.
  20. Supermemory raises $3 million with the best memory engine for LLMsToday, I am excited to announce our first funding round to accelerate our mission of building an interoperable, scalable and reliable memory for LLMs and agents. Memory is one of the hardest challenges in AI right now.
  21. Mem0 vs Supermemory: Why Scira SwitchedScira AI moved its production memory layer from Mem0 to Supermemory. This is what failed, what improved, and how the team evaluated the two systems.
  22. Never Record Again: How Montra Uses Supermemory to Rethink Video CreationCampbell Baron, the founder of Montra, has been making videos since he was twelve. By thirteen, he was already doing brand work. Today, he’s betting on a very different future for creators: a world where recording is the exception, and most videos are generated from scratch.
  23. Unified Memory That Works Where You Work: Your Second Brain With SupermemoryHi everyone, I’m Dhravya, the founder of Supermemory. I want to start with a little story behind why this product means so much to me. You can also skip straight to what it is and how it works below.
  24. Supermemory just got faster on PlanetScaleWhat is Supermemory? Supermemory completes the missing part of the LLM puzzle: memory. Just as memory is crucial for human intelligence, it's essential for truly intelligent AI systems.
  25. Faster, smarter, reliable infinite chat: Supermemory IS context engineering.People are obsessed with prompts and prompt engineering. Sure, what you say is important, but what the model knows when you say it is the difference between a stateless text generator and an intelligent AI system. In short, context is the most crucial component.
  26. We solved AI API interoperabilityOne API to rule them all, One spec to find them, One library to bring them all and in the TypeScript, bind them. When we were building the Infinite Chat API, initially, we only supported the OpenAI format. This was fine, until a lot of our customers started asking for more.
  27. The Wow Factor of Memory - How Flow Used Supermemory To Build Smarter, Stickier ProductsOverview: Flow is a note-taking app built around a bold vision: to create a more personal, context-aware writing experience powered by AI. At the heart of this mission is memory.
  28. The UX and technicalities of awesome MCPsLast month, we launched the Supermemory MCP, mostly to test our own infrastructure and get some initial traction. It blew up. To my absolute surprise, the initial launch itself got half a million impressions (!!!). Then, we launched and got #2 on ProductHunt too.
  29. Architecting a memory engine inspired by the human brainLanguage is at the heart of intelligence, but what truly powers meaningful interaction is memory — the ability to accumulate, recall, and contextualize information over time. Large Language Models (LLMs) have mastered language, but memory remains their Achilles’ heel.
YOUR PRIVACY

Change or withdraw any time via Cookie settings in the footer. Read our cookie notice.