Workflow:Langchain ai Langgraph Persistence and Memory Setup
| Knowledge Sources | |
|---|---|
| Domains | LLM_Ops, Data_Persistence, Agent_Orchestration |
| Last Updated | 2026-02-11 15:00 GMT |
Overview
End-to-end process for configuring LangGraph's persistence layer using checkpoint savers for execution state and stores for cross-thread long-term memory.
Description
This workflow covers setting up LangGraph's dual persistence system: checkpointers for saving graph execution state (enabling resume, replay, and time-travel debugging) and stores for persistent key-value data that spans across threads (enabling long-term memory, user profiles, and shared knowledge). Checkpointers capture the full channel state at each superstep, while stores provide a hierarchical namespace-based key-value interface with optional semantic search via embeddings. The combination enables agents with both short-term working memory (checkpoints) and long-term persistent memory (stores).
Usage
Execute this workflow when building agents that need conversational memory across interactions, durable execution that survives failures, time-travel debugging to inspect past states, or long-term knowledge persistence that spans across different conversation threads. This is essential for any production LangGraph deployment where state must survive process restarts.
Execution Steps
Step 1: Choose a Checkpoint Backend
Select the appropriate checkpoint saver based on your deployment requirements. LangGraph provides `InMemorySaver` for development, `SqliteSaver` for lightweight persistent storage, and `PostgresSaver` for production-grade persistence. Each implements the `BaseCheckpointSaver` protocol with `get_tuple()`, `put()`, `list()`, and `put_writes()` operations.
Key considerations:
- `InMemorySaver`: No persistence, data lost on restart; suitable for testing only
- `SqliteSaver`: File-based persistence; good for single-process deployments
- `PostgresSaver`: Full ACID compliance, concurrent access; production recommended
- Each has both sync and async variants (e.g., `AsyncSqliteSaver`, `AsyncPostgresSaver`)
Step 2: Initialize the Checkpointer
Create and configure the checkpoint saver instance. For database-backed savers, establish the connection and run the setup step to create required tables. The checkpointer uses a serializer (default: `JsonPlusSerializer`) to encode state for storage.
Key considerations:
- Call `setup()` once per database to create checkpoint tables
- Use connection pools for Postgres in production (via `psycopg_pool`)
- `from_conn_string()` factory methods simplify connection setup
- Context managers (`with` / `async with`) handle connection lifecycle
Step 3: Compile Graph with Checkpointer
Pass the checkpointer to `compile()` when building the graph, or to `create_react_agent()` for prebuilt agents. This enables automatic state persistence at each superstep of execution. Every `invoke()` or `stream()` call must include a `thread_id` in the config to identify the execution thread.
Key considerations:
- The `thread_id` is the primary key for checkpoint storage
- Reuse the same `thread_id` for multi-turn conversations
- Use unique `thread_id` values for independent execution threads
- The `checkpoint_ns` allows namespace isolation within a thread
Step 4: Configure a Store for Long-Term Memory
Set up a `BaseStore` implementation for persistent data that spans across threads. Stores use hierarchical namespaces (tuples of strings) to organize data, and support `get()`, `put()`, `search()`, and `delete()` operations. Optionally configure embedding-based semantic search by providing an index configuration with dimensions and an embedding function.
Key considerations:
- Stores are independent of checkpointers; they serve different purposes
- Namespace hierarchy enables per-user, per-org, or per-topic scoping
- Semantic search requires embedding configuration (`dims`, `embed`, `fields`)
- TTL configuration enables automatic expiration of stale data
- Pass the store to `compile(store=...)` to make it available in graph nodes
Step 5: Access State and Memory in Nodes
Within graph nodes, access the checkpoint state via the state parameter and the store via `InjectedStore` annotations on tool parameters or by using the config. Use `get_state()` on the compiled graph to inspect the current state externally. Use `update_state()` to modify state from outside the graph.
Key considerations:
- Nodes receive current state automatically as their first parameter
- Tools access the store via `InjectedStore` annotation for dependency injection
- `graph.get_state(config)` retrieves the latest checkpoint for a thread
- `graph.update_state(config, values)` modifies state externally
- `graph.get_state_history(config)` lists all checkpoints for time-travel
Step 6: Manage Thread Lifecycle
Handle thread cleanup by deleting old checkpoints with `delete_thread()`. List checkpoints for auditing with `list()`. Fork execution from a past checkpoint by providing a specific `checkpoint_id` in the config. This enables time-travel debugging, branching conversations, and state management.
Key considerations:
- `list(config)` returns checkpoints newest-first for a thread
- Provide `checkpoint_id` in config to resume from a specific past state
- `delete_thread(thread_id)` removes all checkpoints for cleanup
- Each checkpoint has metadata including `source`, `step`, and `parents` for tracing