Skip to Content
DeerFlow

Checkpoints and Delta Channels

🗃️

A checkpoint is one thread’s persisted state at one step. database.checkpoint_channel_mode decides how the message channel inside it is stored: full keeps the complete message list in every checkpoint, delta leaves the list out of per-step checkpoints, appends each step’s writes, and reconstructs the list when a read needs it. The default is full.

Every DeerFlow run writes thread state to a checkpoint after each step: the message list, the goal, sandbox handles, durable context, and any channels contributed by middleware. The message list dominates that state in a long run, so how it is represented on disk decides how much a store retains after N turns: full mode retains a quadratic amount of it, and delta mode shrinks that quadratic component by a factor set by the snapshot cadence rather than removing it. This manual covers both representations, the switch that selects one, and what each choice costs an operator.

How to read this manual

ReaderStart with
Chat usersThis page, Quick Start, Channel Modes
OperatorsQuick Start, Snapshot Cadence, History Cache, Operating Checkpoints, Observability, Troubleshooting
Integration developersChannel Modes, Resume and Rollback, Reference

Concepts

  • Checkpoint: one thread’s channel values at one step, plus the metadata LangGraph attaches to it — checkpoint id, parent link, pending writes, counters. Reads, resumes, and branches all start from a checkpoint.
  • Channel: one field of the thread state schema, with its own value type and update rule. A compiled graph carries a channel table that decides how each channel is stored and merged. The mode changes only the messages channel.
  • Reducer: the function that folds incoming writes into a channel’s value. Delta mode’s message reducer is merge_message_writes, which applies add_messages semantics in linear time.

Why delta exists

In full mode every checkpoint carries the complete channel values, so each step re-serializes the whole message list, and all of those checkpoints are retained: total storage grows O(N²) in turns.

In delta mode the message list is a LangGraph DeltaChannel. A non-snapshot checkpoint stores no message value in channel_values, each step’s updates are appended as writes, and a read reconstructs the list by replaying the ancestor writes through the reducer. That removes the whole-list serialization from most checkpoints — but it does not remove the quadratic term, because every snapshot_frequency writes a _DeltaSnapshot holds the entire message list as of that step, and those snapshots are retained like any other checkpoint.

Let K be snapshot_frequency. The two quantities a capacity plan depends on are different:

Quantityfulldelta
Marginal cost of one stepRe-serializes the whole list into one more retained checkpointAppends that step’s writes; every K writes also stores a full-list snapshot
Total retained after N turnsO(N²)O(N²/K + N)

Delta therefore divides the quadratic component by roughly K — 10 by default — instead of deleting it. Fewer snapshots mean a smaller residual and slower reads, since materialization replays from the nearest one (Snapshot Cadence). Nothing in DeerFlow prunes those snapshots yet, so size a store from the retained total rather than from the per-step write cost (Operating Checkpoints).

fulldelta
Checkpoint payloadComplete channel_values, message list includedNo message blob on non-snapshot steps; a sentinel _DeltaSnapshot blob appears every snapshot_frequency writes
Step updatesFolded into the next checkpoint’s payloadStored as per-step writes
Read pathStored values are used directlyReconstructed from the nearest stored snapshot plus replayed writes
Total retained after N turnsO(N²)O(N²/K + N), where K = snapshot_frequency

The mode is a process-level, restart-required choice. Each process resolves it once, before the first graph is compiled, and cannot change it afterwards; every process sharing one checkpoint database must use the same value. Quick Start covers the switch, and Snapshot Cadence covers the second frozen knob, the snapshot cadence.

Terminology

TermMeaning
CheckpointA thread’s persisted channel values at one step, plus LangGraph’s checkpoint metadata.
ChannelOne field of the thread state schema, with its own value type and update rule.
ReducerThe function that folds writes into a channel value.
Delta channel (DeltaChannel)LangGraph’s reducer channel that keeps no full value in the checkpoint and reconstructs it by replaying ancestor writes.
SentinelThe marker stored in a delta channel’s place in channel_values; a stored _DeltaSnapshot terminates the ancestor walk for that channel.
SeedThe stored value at the nearest ancestor whose channel_values is populated. Reconstruction starts from it.
WritesPer-step channel updates stored in their own table. In delta mode they are load-bearing replay state, not garbage.
MaterializeReconstruct a channel’s value from the seed plus replayed writes.
Cadence (snapshot_frequency)How many per-step writes pass before a full messages snapshot is stored.
Ancestor chainThe checkpoint parent chain. A delta checkpoint’s history is a pure function of its sealed ancestor chain.
ForkA second child of the same checkpoint. Delta mode cannot fork correctly; a resume is linearized onto the head instead.
LinearizationRe-expressing a resume from an older checkpoint as a replace-style write on the current head.
RollbackRestoring the pre-run head after a cancelled run.
CompactionReplacing the message list with a summary, written through an Overwrite so the replace survives the append reducer.
Retention / pruneDeleting checkpoint rows. In delta mode the writes rows that reconstruction depends on must survive.
CacheThe delta-only history cache that memoizes materialized channel histories.
FrozenResolved once per process before the first graph is built; a different value later is an error, and changing it needs a restart.
Gateway / embeddedThe async Gateway path versus the sync TUI or in-process DeerFlowClient path.