Memory (in LangChain)

LLMs are stateless, so a LangChain app needs memory to hold a conversation. This is the part of LangChain that has changed the most: the classic ConversationBufferMemory classes are deprecated, replaced by LangGraph persistence — a checkpointer for the current conversation and a store for facts that outlive it. If you learned LangChain memory a while ago, this is the subtopic to re-learn.

💡 In one line: LangChain memory now means LangGraph persistence — checkpointers for short-term (thread) memory and stores for long-term (cross-session) memory.

Why Memory?

Each LLM call is independent — without memory, the model forgets the last turn. Memory stores conversation history and facts and injects them back into the prompt, giving the app continuity.

The Big Shift (Important)

The classic memory classes — ConversationBufferMemory, ConversationBufferWindowMemory, ConversationSummaryMemory, ConversationEntityMemory, and ConversationChain — are deprecated (since v0.3.1, slated for removal). They were built for a pre-tool-calling world and had no concept of multiple users or threads — one object meant one conversation, with no real persistence.

The replacement: LangGraph persistence.

Two Layers: Checkpointer & Store

  • Checkpointer → short-term memory. Persists the graph state (including message history) for a thread_id — one conversation/session. Survives restarts with a durable saver.
  • Store → long-term memory. Saves facts as JSON documents under a namespace (e.g. a user_id), shared across all threads and recallable anytime.

The classic mistake: confusing thread_id with user_id. A thread_id scopes a single session; a user_id scopes across sessions.

Checkpointers (Short-Term)

  • InMemorySaver / MemorySaver — development only.
  • SqliteSaver — local persistence.
  • PostgresSaver — production.

Pass one at compile time and invoke with a thread_id; the agent then picks up where the conversation left off — even after a restart.

Stores (Long-Term)

InMemoryStore for dev, a DB-backed store in production. Memories are stored as JSON under a namespace + key (like folders and files), and can be searched semantically if you attach an embedding function.

Note: long-term memory needs explicit read/write — LangGraph won't extract facts for you automatically.

The Memory Flow

Whiteboard
Whiteboard diagram

Code Example


Same thread_id → it remembers. Different thread_id → a fresh conversation.

Managing Long Conversations

History outgrows the context window, and LLMs degrade on very long contexts. Two standard fixes:

  • Trimming — keep the last k messages (trim_messages).
  • Summarising — compress older turns into a running summary.

Memory Types (Long-Term)

Mirroring human memory: semantic (facts), episodic (past experiences), and procedural (learned rules/behaviour).

Beyond the Basics

LangMem (LangChain's SDK) adds LLM-driven memory extraction and consolidation over LangGraph's store; Zep and Mem0 are popular third-party memory layers.

Best Practices

  • Use a durable checkpointer in production (Postgres, not in-memory).
  • Keep thread_id (session) and user_id (person) distinct.
  • Trim or summarise long histories.
  • Write long-term facts explicitly, and decouple your memory layer where you can — this API has churned repeatedly.

A Note on Currency

As of 2026, classic memory classes are deprecated (removal planned) and LangGraph persistence — checkpointer + store — is the supported path. This area changes fast; check docs.langchain.com before building.

Summary

  • LangChain memory is now LangGraph persistence; the classic classes are deprecated.
  • Checkpointer = short-term, scoped to a thread_id; Store = long-term, scoped to a namespace/user.
  • Use InMemory for dev, Sqlite/Postgres for production.
  • Trim or summarise long histories to fit the context window.
  • Long-term memory is explicit — LangGraph doesn't extract facts for you. EOF echo created