LangChain/Memory & Middleware
Intermediate12 min

Memory Storage Backends

BaseChatMessageHistory is the interface every storage backend implements, but picking the wrong backend — or ignoring LangGraph checkpointers entirely — will cost you in production. This article covers how to decide, configure, and operate each option.

Quick Reference

  • All backends implement BaseChatMessageHistory: add_messages(), messages, clear() — sync and async variants
  • InMemoryChatMessageHistory — development only, lost on restart
  • RedisChatMessageHistory — low-latency production; use redis_url= (not url=) and always set TTL
  • SQLChatMessageHistory — durable, queryable; add a cleanup job or the table grows indefinitely
  • LangGraph checkpointers (PostgresSaver, SqliteSaver) — use these instead when you need full agent state, interrupts, or branching
  • Factory function is the only swap point — the chain never imports the backend directly
  • Redis reads are sub-millisecond; SQL reads are typically 5–20ms with a connection pool
  • Without TTL on Redis, abandoned sessions accumulate — memory grows until the instance OOMs

Two Persistence Models: Checkpointers vs Chat History

LangChain gives you two separate persistence systems and they are not interchangeable. Understanding which one you need before picking a backend saves a painful migration later.

ModelWhat it persistsWhen to use it
BaseChatMessageHistoryThe message list for one conversation session — nothing elseYou're using RunnableWithMessageHistory or managing history manually in a simple LCEL chain
LangGraph CheckpointerFull agent state: messages + any state fields + interrupt points + branching historyYou're using LangGraph agents, need human-in-the-loop interrupts, or need to resume a multi-step workflow
Don't bolt chat history onto a LangGraph agent

If your agent is built with LangGraph, use a checkpointer — not RunnableWithMessageHistory. Wrapping a LangGraph agent with RunnableWithMessageHistory means you have two competing persistence layers. The checkpointer already stores messages as part of state; the chat history backend stores a duplicate. Pick one.

The rest of this article covers BaseChatMessageHistory backends. The LangGraph checkpointers section at the end covers the alternative path and when to take it.