Does LangGraph Remember Between Runs?
Does LangGraph Remember Between Runs? The short answer: only inside one thread. LangGraph's checkpointer saves your graph's state under a thread_id, so the same conversation can resume after a crash or a restart. A new thread_id starts with a blank slate. For memory that survives across threads and sessions, you need LangGraph's store, a separate system you have to wire in deliberately. What does a LangGraph checkpointer actually remember? A checkpointer snapshots your graph's state after ev
Does LangGraph Remember Between Runs?
The short answer: only inside one thread. LangGraph's checkpointer saves your graph's state under a thread_id, so the same conversation can resume after a crash or a restart. A new thread_id starts with a blank slate. For memory that survives across threads and sessions, you need LangGraph's store, a separate system you have to wire in deliberately.
What does a LangGraph checkpointer actually remember?
A checkpointer snapshots your graph's state after every node runs and keys it by thread_id. That gives you four things:
- Conversation continuity. The same thread picks up where it left off, even after the process restarts, as long as the checkpointer itself is durable.
- Crash recovery. If a node fails mid-run, LangGraph resumes from the last saved checkpoint instead of starting over.
- Human-in-the-loop. You can pause a thread, let a person review or edit the pending state, and resume.
- Time travel. You can rewind a thread to any earlier checkpoint for debugging.
What the checkpointer remembers is where this conversation was. What it does not remember is anything outside that conversation.
One more detail that bites people: the default checkpointer in tutorials, InMemorySaver, keeps checkpoints in RAM. Restart the process and everything is gone. LangGraph's own docs treat it as a development tool and recommend PostgresSaver for anything real.
Why does a new thread_id start from zero?
Because threads are isolated by design. Each thread_id is its own island of state. The checkpointer for the new thread has no way to reach into the old thread's snapshots, and it was never meant to. A checkpointer answers "what was happening in this conversation?" It has nothing to say about "what do I know about this user across all conversations?"
This is the exact point where scheduled and multi-session agents break. A nightly job that runs your LangGraph agent with a fresh thread_id every night gets a brand-new agent every night. Preferences learned on Monday, corrections made on Tuesday, facts gathered on Wednesday: all of it is invisible on Thursday, because Thursday is a different thread.
What is the LangGraph store, and how is it different?
The store is LangGraph's second persistence system, and it exists precisely for the cross-thread case. Where the checkpointer is automatic and thread-scoped, the store is deliberate and cross-thread:
| Checkpointer | Store | |
|---|---|---|
| Scope | One thread (thread_id) |
All threads |
| What it holds | Graph state snapshots | Application-defined data: preferences, facts, user profiles |
| Saved | Automatically, after each node | Only when you call store.put() |
| Read by | Resuming a known thread | Namespace lookup or search from any thread |
In code, the difference is one argument at compile time and a deliberate write inside your nodes:
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
store.put(
namespace=("users", user_id),
key="preferences",
value={"report_format": "bullet points", "timezone": "America/Denver"},
)
graph = builder.compile(checkpointer=checkpointer, store=store)
Most production LangGraph agents run both: the checkpointer for the current thread's working state, the store for durable knowledge that should follow the user across sessions. InMemoryStore is the dev stand-in; production setups point the store at Postgres or Redis, on the same database instance as the checkpointer if you want operational simplicity.
What is the most common LangGraph memory mistake?
Treating the checkpointer as long-term memory. A September 2026 field guide to LangGraph memory put it bluntly: most developers migrating to LangGraph use the checkpointer as a drop-in for the old ConversationBufferMemory and expect it to remember user preferences across sessions. It does not. The preferences land in the checkpointer, scoped to the old thread_id, and a returning user on a new thread gets a blank slate.
Teams usually discover this in production, when a real user reports that the agent has forgotten everything about them. The fix is a small refactor with an outsized payoff: decide at write time whether a piece of information belongs to the thread or to the user, and send it to the checkpointer or the store accordingly.
How do you give a LangGraph agent memory across runs?
Follow this ladder, in order. Stop at the first rung that covers your case.
- Persist the checkpointer. Swap
InMemorySaverforPostgresSaver(or SQLite for single-machine setups). This survives restarts and gives you resume, crash recovery, and human-in-the-loop on durable storage. It does not share anything across threads. - Add a store for cross-thread facts. Compile with both a checkpointer and a store. Key the store's namespaces by
user_id, notthread_id: one user has many threads. Write preferences, corrections, and durable facts withstore.put(); read them back at the start of each run withstore.get()orstore.search(). - Prune what you persist. Checkpoint tables grow fast under sustained traffic. Add a retention policy, for example a scheduled job that deletes checkpoints older than N days, so storage does not grow without bound.
When should you reach for a hosted memory layer instead?
There is a third option for teams that do not want to run this infrastructure at all. Vilix AI is a cloud-hosted memory layer: you connect once and manage nothing. Any MCP-compatible agent can read and write it, a headless agent connects with an API key as a Bearer header to https://api.vilix.ai/mcp, and it saves full conversation history instead of just facts, recalling it semantically across threads, sessions, and tools. One memory follows your LangGraph agent, your n8n workflows, and your coding assistants alike.
Use the store plus PostgresSaver when your memory never needs to leave the LangGraph runtime. Reach for the hosted layer when you want zero infrastructure to operate and one shared memory across every tool your agents run in.
Frequently asked questions
Does LangGraph remember between runs?
Within one thread, yes: the checkpointer restores the thread's state, so the same conversation continues across runs and restarts. Across threads, no: each new thread_id starts empty. Cross-thread memory needs the store.
What is the difference between a LangGraph checkpointer and a store?
A checkpointer saves thread-scoped graph state automatically after every node. A store persists application-defined data across all threads, but only what you explicitly write to it. Production agents typically use both.
Why does my LangGraph agent forget the user on a new conversation?
Because the facts were saved in the checkpointer, which is scoped to the old thread_id. Move user-level facts (preferences, corrections, durable context) into the store, keyed by user, and read them at the start of each run.
Do I need a database for LangGraph memory in production?
Yes. InMemorySaver and InMemoryStore lose everything on process restart. Use PostgresSaver for the checkpointer and a Postgres or Redis backed store for cross-thread memory, plus a retention policy for old checkpoints.
Related reading: vilix.ai