Memory, State, and Persistence

Objectives

Distinguish message history, run state, checkpoints, threads, and long-term memory. Understand how LangGraph persistence supports recovery and human-in-the-loop behavior, and design rules for data isolation, expiration, deletion, and side-effect replay.

First distinguish five things

ConceptMeaningTypical lifetime
Message historyUser, model, and tool messagesOne conversation or thread
Run stateStructured fields needed for the next node to continueOne graph run and its recovery
CheckpointState snapshot at a particular super-stepPersisted according to a retention policy
ThreadIdentifier organizing a sequence of checkpointsAn ongoing interaction
Long-term memory storeInformation retrieved across threadsGoverned by subject, purpose, and expiration policy

Do not call all of them “memory.” For example, an order ID belongs in structured state, a user’s long-term preferences may belong in a store, and a retrieved policy document is knowledge-base material—not user memory.

Current facts about LangGraph persistence

Official documentation states that after a graph is compiled with a checkpointer, LangGraph saves checkpoints at execution boundaries and organizes them by thread. At invocation time, configurable.thread_id selects the durable cursor. Passing an ordinary dictionary to an existing thread starts a new run on its latest state. Only when the target is actually stopped at an interrupt should you pass Command(resume=...) to return a value to that interrupt. A new ID has no historical state, but you should not rely on the runtime to reject an erroneous resume sent to a new ID automatically.

A thread_id is not an approval credential or authorization proof. Before resuming, the application must validate tenant/subject ownership, snapshot.next, and pending interrupts. A completed, unknown, or differently paused thread should fail closed in the wrapper.

Do not use an in-process saver as production persistence. Tests can use InMemorySaver; production should choose a reliable backend and verify backups, concurrency, encryption, migration, and retention policies.

The current runtime’s durability mode also changes checkpoint write timing: sync writes synchronously before the next step, async writes in parallel with the next step while retaining a smaller crash window, and exit saves only when the run exits, errors, or interrupts. This course’s real recovery project explicitly uses sync; that still does not make an external API and a checkpoint one transaction.

Thread ID is part of the isolation boundary

A thread ID must not be generated by the model or trusted merely because a client supplies it. The server should map tenant, user, and session to an unguessable internal ID and verify ownership again on every read and write. Reusing an ID incorrectly can expose user A’s history to user B.

Record at least tenant, subject, thread_id, created_at, expires_at, schema_version, and application_version. Do not emit complete sensitive messages in logs.

Short-term memory is not an unlimited chat log

Context windows and budgets are finite. Common strategies include:

  • Retain only the latest N turns; simple, but early constraints can be lost.
  • Truncate by token budget; more stable than counting messages.
  • Summarize older history; saves context, but a summary can misstate facts.
  • Selectively retain business fields; more reliable, but requires a schema.

Obtain business truth from a database or structured state instead of asking a model to infer it from natural-language history on every turn. Every summary should record its source range and generation version; important facts must remain checkable against the original record.

Long-term memory needs a write gate

For each long-term memory item, consider at least: subject, content, source, fact/inference label, creation time, expiration time, visibility scope, purpose, and deletion method. A model inference that “the user likes red” must not masquerade as user confirmation; sensitive attributes must not be retained merely because they may be useful later.

Before writing, ask: Does the task need it? Does the user expect it? Is storage permitted? When will it be deleted? Can it be withdrawn? How are different tenants isolated?

Recovery and side effects

Recovery can re-execute a node. Pure computation is usually replayable, but sending email, charging money, or writing a database requires an idempotency key or a receipt lookup first. Official persistence documentation also describes pending writes: writes from successfully completed nodes in the same super-step can support recovery and avoid needless reruns. The application still has to design exactly-once business semantics for external side effects; a checkpoint is not a distributed transaction.

An old checkpoint can also be incompatible with new code, a prompt, a tool schema, or a state schema. Verify versions before resuming. If migration is impossible, fail explicitly or use human recovery; never silently reinterpret old fields.

Practice

For a “travel-planning assistant,” design:

  1. Current itinerary state: destination, dates, budget, and items awaiting confirmation.
  2. Message history: user and tool messages.
  3. Long-term memory: explicitly confirmed seat preferences and their expiration rules.
  4. Data that must not be stored: document originals and payment credentials.
  5. Server-side thread_id mapping rules.
  6. The idempotency key, receipt lookup, and recovery flow for a “book ticket” node.

Then write six tests: thread isolation, continued conversation on the same thread, expiration deletion, a summary not overwriting structured fields, recovery not booking twice, and an old schema refusing recovery.

Self-check

  • Distinguish state, checkpoint, thread, and a long-term store.
  • Explain what a shared thread_id means and what incorrect reuse can cause.
  • Explain the difference between a test saver and a production persistence backend.
  • Design recovery for an external side effect without executing it twice.

Next

Continue to LangGraph Boundaries, Approval, Recovery, and Evaluation to map state to explicit graph control.

Source baseline

Official facts and the locked runtime were checked on 2026-07-19.