groundy
Agents & Frameworks

What LangGraph Checkpointing Guarantees, and What You Build Yourself

LangGraph saves a state snapshot at every superstep, but failure detection, resumption and duplicate prevention remain yours to build, per the Diagrid critique.

Published Updated 5 references
On this page7 sections

LangGraph writes a snapshot of graph state at every superstep, scoped to a thread_id, and a failed run resumes with one more invoke call carrying that identifier. That is a real capability, and for many workloads it is enough. It is also, as a February 2026 Diagrid analysis puts it, a save point: a snapshot that you, the developer, are responsible for detecting the need to use, triggering, and coordinating to avoid duplicate work. That is a different thing from a runtime that guarantees a workflow runs to completion.

What follows is what LangGraph’s persistence model actually guarantees, where CrewAI’s persistence sits relative to it, and when a durable-execution runtime earns its adoption cost. The short version: the guarantee is conditional on your checkpointer, your monitoring, and the safety of re-running your own steps.

What LangGraph Checkpointing Actually Gives You

Per the Diagrid writeup, when you compile a graph with a checkpointer (PostgresSaver and SqliteSaver are the examples it names), the runtime automatically saves a snapshot of the graph state at every superstep, each tick of the graph where one or more nodes execute. Each checkpoint is scoped to a thread_id. To resume a failed graph, you call graph.invoke() with the same thread_id, and LangGraph picks up from the last successful superstep. The writeup shows the shape of it, comment included:

config = {"configurable": {"thread_id": "workflow-123"}}
try:
result = graph.invoke({"query": "process this"}, config=config)
except Exception:
# You detected the failure. Now you resume manually.
result = graph.invoke(None, config=config)

That comment is the whole story. The framework saves; you detect, and you re-invoke.

Retries live in a separate drawer. A RetryPolicy can be attached to individual nodes for automatic retries with exponential backoff (max_attempts, backoff_factor). When retries are exhausted, the exception is raised. Diagrid’s list of what does not happen next is worth reading literally: no built-in fallback routing, no dead-letter queue, no notification system. The error is persisted in the checkpoint, and that is it. Retries address transient errors inside a live process. They do nothing for a dead one.

Who Does the Recovery Work

The limitation is less about what gets saved than about who acts next. Diagrid identifies three gaps:

  • No automatic failure detection. If your process crashes, no one knows. There is “no supervisor, no watchdog, no heartbeat mechanism.” The workflow is dead until something external notices, and that something is you.
  • No automatic resumption. Once the failure is detected (how?), you call invoke(None, config=config) with the correct thread_id. With hundreds of concurrent workflows, you are building failure-detection-and-retry infrastructure yourself.
  • No duplicate execution prevention. Two processes can resume the same thread_id simultaneously, and LangGraph has no built-in coordination to stop both from executing. Distributed locking and lease coordination are your job.

A fourth constraint shapes deployment: the open-source library runs in a single process. No distributed execution, no task queue, no worker pool. If that process dies, everything it was running dies with it.

The Conditions That Decide Whether a Checkpoint Helps

Three conditions determine whether a checkpoint is worth anything after a crash, and none is optional.

The checkpointer must outlive the process. This follows directly from the single-process model: a snapshot written to Postgres or SQLite before the crash is what survives; state held only in the dying process is gone. The checkpointer you configure is the entire durability surface. Diagrid names PostgresSaver and SqliteSaver as the standard options; for any third-party backend, verify its crash semantics against that backend’s own documentation rather than assuming the framework’s guarantees transfer.

Something external must detect and re-invoke. The checkpoint model presumes a caller that notices the process died, knows the thread_id, and issues the resume call. That caller is infrastructure you build and, notably, infrastructure that itself needs to survive failures.

Re-execution must be safe. Resume continues from the last successful superstep, so every step after it runs again, side effects and all. If a step already issued a payment or posted to a queue before the crash, resuming re-runs it. The framework cannot know which of your calls were observable; an idempotency key that a step checks before acting is the usual mitigation. And because two processes can resume the same thread concurrently, “safe under replay” has to mean safe under concurrent replay.

CrewAI: Two Persistence Mechanisms, Same Manual Recovery

CrewAI splits persistence in two, per the same analysis. Task Replay re-runs tasks from the most recent crew kickoff; each kickoff saves task outputs locally, and you replay from a specific task (crewai replay -t <task_id>). Flow Persistence uses the @persist decorator to save flow state to SQLite after each successful method execution. Agent-level retries exist via max_retry_limit (default 2), max_iter (default 20), and max_execution_time, but these handle LLM-level errors within a running process.

The gaps run parallel to LangGraph’s, with one difference in granularity. Task replay retains only the last kickoff, with no historical record, so if you are running hundreds of crews and need to identify which failed and replay them, there is no built-in mechanism. @persist does not auto-resume: it saves state after successful steps, but if the process crashes, you must detect the failure, find the persisted flow ID, instantiate a new flow, and route execution past the completed steps yourself, because the framework does not skip them automatically. There is no locking to stop two processes resuming the same flow and duplicating work or corrupting shared state. And CrewAI’s persistence operates at workflow boundaries; it does not persist an agent’s internal ReAct cursor mid-loop unless you explicitly model each tool action as its own persisted step. CrewAI Enterprise adds execution monitoring, but even on the enterprise tier there is no automatic restart of failed crews.

The comparison that matters: LangGraph’s snapshots are automatic at every superstep during a run, while its recovery is manual. CrewAI’s persistence is partly interactive, with replay and a from_pending()/resume() pattern for human-in-the-loop, and its recovery is also manual. Google ADK has pushed resumability furthest of the three, with event-sourced sessions and ResumabilityConfig since version 1.14.0, and lands in the same place: the caller detects the interruption and re-invokes with the original invocation_id. For the broader authoring-model tradeoffs, see the CrewAI vs AutoGen vs LangGraph comparison; durability is one axis among several.

Where Durable-Execution Engines Still Win

The honest comparison is not LangGraph against CrewAI, both of them agent frameworks with checkpoint layers. It is both against systems built around durable execution as the primitive: Temporal and Dapr Workflows. In Dapr’s model, as Diagrid describes it: every await point in a workflow is automatically a checkpoint; before executing any step, the runtime creates a durable reminder, so if the process, the runtime, or the entire cluster crashes, the reminder reactivates the workflow and retries indefinitely without external intervention; on replay, completed activities return their stored results from the event log instead of re-executing; and an actor placement service with consistent hashing distributes work across nodes and rebalances on failure. You write the workflow as linear code. There is no try/catch/resume pattern and no manual thread_id management.

LangGraph gives you the journal and a manual replay entry point. It does not give you the supervisor, the reminder, or the deduplication. The cost on the other side is real: adopting one of these engines means adopting its runtime, its deployment topology, and its programming constraints. LangGraph’s implicit bet is that a checkpointer plus your own watchdog is a smaller commitment than a workflow engine, and for teams already invested in the library that bet can be reasonable. It is not equivalence. Diagrid’s structural claim is that no point release closes this: the frameworks would need to rearchitect their runtimes, and a better checkpointer or a fancier retry policy does not change who owns failure handling. Diagrid also points to Dapr Agents, an agent framework with built-in durable execution co-maintained with NVIDIA, as the option that combines both layers.

Cloudflare’s Version of the Argument

Cloudflare spent Agents Week 2026 pitching durability as a runtime responsibility, and it argues the position from both ends. Dynamic Workers, in open beta to all paid Workers users, are ephemeral V8 isolates for AI-generated code: an isolate starts in milliseconds, runs one snippet, and is thrown away, while files live in a durable workspace (SQLite plus R2) that persists across executions. Agents Week extended that model with Durable Object Facets, which let a Dynamic Worker instantiate a Durable Object with its own isolated SQLite database, and rearchitected Workflows, which Cloudflare describes as a durable execution engine for multi-step applications, to support 50,000 concurrency and 300 creation rate limits. The argument: frameworks should not rebuild storage, consensus, and recovery when the runtime already provides them.

LangGraph is a counter-argument of a different shape. Keep the library, keep your compute, add a checkpointer and a recovery loop of your own. The library is MIT-licensed open source and runs as a single-process Python dependency wherever your application runs. That narrows the case for runtime migration without eliminating it. The three things Diagrid says checkpointing frameworks lack (automatic failure detection, automatic resumption, duplicate-execution prevention) are exactly the things a runtime vendor can compete on, and the Workflows rearchitecture shows Cloudflare doing precisely that.

The Checklist You Still Have to Build

If you are evaluating LangGraph for production durability, the persistence feature itself is the smaller half of the work.

  • A checkpointer that persists outside the process, not an in-process store.
  • External failure detection: a supervisor, watchdog, or heartbeat that you own and that itself survives failures.
  • A re-invocation path that calls invoke(None, config=config) with the correct thread_id, reachable from whatever detects the failure.
  • Locking or lease coordination if more than one process might attempt recovery.
  • Steps that are safe to re-run, since resume replays everything after the last successful superstep, potentially concurrently with another recovering process.
  • A dead-letter story for exhausted retries, because the framework raises and persists the error rather than routing it anywhere.

Checkpointing is a good primitive, and LangGraph’s version of it is automatic and fine-grained: a snapshot per superstep, scoped to a thread, resumable with one call. The teams it serves best already run the surrounding machinery, monitoring that notices a dead process and a job runner that can re-invoke with the right thread_id, with steps that tolerate replay. Teams without that machinery are not really choosing between frameworks on durability. They are choosing between building the missing pieces themselves and adopting a runtime that already has them.

References

Follow the links in the article for context. The supporting material is collected here for further reading.

  1. Cloudflare Dynamic Workersblog.cloudflare.comAccessed
  2. Cloudflare Agents Week in Reviewblog.cloudflare.comAccessed
  3. Diagrid: Checkpoints Are Not Durable Executiondiagrid.ioAccessed
  4. LangGraph Product Pagelangchain.comAccessed
  5. Dapr Workflow Documentationdocs.dapr.ioAccessed

Join the discussion

Share a useful perspective or ask a question about this article.

Discussion guidelinesComments privacy