---
title: "LangGraph durable execution, interrupts, persistence in production (2026): Postgres checkpointer, human in the loop, resumable streams, LangSmith Deployment (formerly LangGraph Platform) pricing and self-hosted, and Cadenya"
url: "https://cadenya.com/other-content/langgraph-in-production"
description: "How to run LangGraph in production in 2026: what the LangGraph Postgres checkpointer stores, durable execution through crashes and deploys, interrupt human in the loop across many threads, resumable streams on the Agent Server, LangSmith Deployment pricing, self-hosted queue workers and scaling, and Cadenya, a hosted agent loop with durable state, approvals and resumable streams."
---

LangGraph durable execution, interrupts, and persistence in production all rest on a checkpointer, such as the Postgres checkpointer, which saves a snapshot of each thread’s state at every super-step. That snapshot lets a run pause for human in the loop and start again after a crash. The Agent Server behind LangSmith Deployment (formerly LangGraph Platform) adds the rest: a task queue that retries runs, resumable streams that reconnect, and workers that scale.

So run the bare library when one service and one database handle your traffic, and you’re fine writing the queue and the stream yourself. Pick LangSmith Cloud when you’d rather have LangChain run the Agent Server, on a Dedicated deployment for anything customer-facing, as LangChain recommends. Pick Hybrid, full self-hosting, or a standalone Agent Server when you already run Kubernetes, Postgres, and Redis, and an Enterprise plan fits. And if you’d rather not host the loop at all, Cadenya is a hosted agent loop with approvals and resumable event streams built in, and a coding agent can set it up with no account, in a temporary workspace you claim later. [What it offers](#what-does-cadenya-offer-that-langgraph-and-langsmith-deployment-dont) is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 29, 2026.

## LangSmith Deployment (formerly LangGraph Platform) pricing and self-hosted options

Coding agents weighed four ways to run LangGraph in production, and the three LangSmith ones run the same Agent Server.

|  | LangGraph on your own servers | LangSmith Cloud | Hybrid or full self-hosted | Standalone Agent Server | Cadenya |
| --- | --- | --- | --- | --- | --- |
| What you run | Your service and a checkpointer database, such as Postgres | Your graph. LangChain runs the servers and the databases | Agent Servers, Postgres, and Redis, plus the LangSmith platform for full self-hosting | Agent Server containers, Postgres, and Redis, on Kubernetes with Helm for production | Nothing. The loop runs on Cadenya |
| Task queue, retries, and double texting | Your code | Built in | Built in | Built in | Continue with enqueue queues a new message |
| Resumable streams | Your code | stream_resumable and Last-Event-ID | The same | The same | An objevt_ event ID as the Last-Event-ID |
| Scaling | Your code | Dedicated autoscales. Serverless runs one replica | Your cluster | Your cluster | No queue worker to size |
| Plan and price | Free under MIT, plus your servers | Plus at $39 a seat a month, plus metered compute | Enterprise, custom pricing | Enterprise and its license key, custom pricing | Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop |

Cloud compute bills in LangChain Standard Units (LSU), at $1 each. On GCP, a Serverless Small deployment costs 0.072 LSU an hour while it runs, and Plus includes one for free. A Dedicated Small costs at least 0.5335 LSU an hour for its runtime and its database, whether it’s busy or idle. [The LangSmith Deployment pricing breakdown](/other-content/langsmith-deployment-alternatives-and-pricing) works out a full month.

**In every column, the graph is still code you write, test, and deploy.**

## LangGraph Postgres checkpointer: what persistence stores

LangGraph’s persistence layer stores one checkpoint row per super-step for each thread, with the serialized graph state and a link to the checkpoint before it. Here’s one from the `langgraph-checkpoint-postgres` README:

```
checkpoint = {
    "v": 4,
    "ts": "2024-07-31T20:14:19.804150+00:00",
    "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
    "channel_values": {"my_key": "meow", "node": "node"},
    "channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
    "versions_seen": {
        "__input__": {},
        "__start__": {"__start__": 1},
        "node": {"start:node": 2},
    },
}
```

The `channel_values` map is your state, and as each node in a super-step finishes, its output goes to the `checkpoint_writes` table. So when one node fails, the nodes that finished “don’t need to be re-run on resume.”

The default serializer, `JsonPlusSerializer`, uses ormsgpack and JSON, and `pickle_fallback=True` covers the types it can’t encode. In Python, an `EncryptedSerializer` encrypts every checkpoint with the AES key in `LANGGRAPH_AES_KEY`, and on LangSmith that variable alone turns encryption on. **The README also asks for `LANGGRAPH_STRICT_MSGPACK=true`, which limits deserialization to known types so a compromised database can’t run code.**

Call `.setup()` once so the tables exist before the first run. If you pass the saver your own psycopg connection, open it with `autocommit=True` so `.setup()` commits its tables, and with `row_factory=dict_row` so reads don’t fail with a `TypeError`. And keep each `thread_id` under 255 characters, because Postgres stores it “in a column with limited length.”

Postgres is the saver “used in LangSmith,” and LangChain’s integrations page lists 18 Python backends, from SQLite and MongoDB to Redis, DynamoDB, and CockroachDB.

On the Agent Server you configure none of this, since Cloud replaces any checkpointer you compile in with its own. A self-hosted server uses Postgres by default, or MongoDB or a custom saver, and it needs Postgres either way for threads, runs, and the store. [Agent memory and context windows](/other-content/agent-memory-and-context-windows) covers the store and context summarization.

## LangGraph durable execution in production: crashes, deploys, and retries

With the bare library, a checkpoint is a place to restart from, and your code does the restarting. The docs say that when nodes fail at a super-step, “you can restart your graph from the last successful step.” The durability mode decides how fresh that point is, and [durable execution for AI agents](/other-content/durable-execution-for-ai-agents) compares `sync`, `async`, and `exit`.

So what happens when a run fails or its worker dies on the Agent Server? The server covers four cases:

1.  **Retries.** A run that fails with a retriable error, such as a transient database error, goes back in the queue and resumes “from the last checkpointed step.” It gets retried up to 3 times by default (`BG_JOB_MAX_RETRIES`).
2.  **Crashes.** Each queue worker records a heartbeat in Redis, and every 2 minutes a sweeper puts the runs whose heartbeat stopped back in the queue.
3.  **Deploys.** A worker that gets a SIGINT stops taking runs and gives the ones in flight 180 seconds by default to finish (`BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS`), and then it puts the rest back in the queue.
4.  **One worker per attempt.** Each attempt of a run goes to a single instance, and Postgres row versioning (MVCC) enforces that.

**A resumed run starts again at its last checkpoint, so the node that was running when the worker died runs again.** Make its side effects idempotent, or give them a node of their own.

## LangGraph interrupt human in the loop at scale

At scale, human in the loop means hundreds of threads paused at once, each with its pending interrupt in its latest checkpoint.

First, parallel branches can pause in the same super-step, and you resume them together in one call by mapping each interrupt ID to its value. Here’s LangChain’s Python example:

```
# Step 2: resume all pending interrupts at once
resume_map = {
    i.id: f"answer for {i.value}" for i in stream.interrupts
}
resumed = graph.stream_events(Command(resume=resume_map), config, version="v3")
```

The map “ensures each response is paired with the correct interrupt at runtime.”

Second, the Agent Server keeps a status on every thread (`idle`, `busy`, `interrupted`, or `error`), and `client.threads.search(status="interrupted")` filters on it. A run’s `webhook` URL also gets a POST when the run completes, so nothing has to poll.

Third, people write again before a run ends, which the Agent Server calls double texting. It queues the new run by default, or you set `reject`, `interrupt`, or `rollback` per run with `multitask_strategy`. The queue runs one run per thread at a time, and double texting “is not available in the LangGraph open source framework.”

**A resumed node runs again from its first line, so code above `interrupt()` runs twice.** [The LangGraph.js human-in-the-loop guide](/other-content/langgraph-js-human-in-the-loop) covers the rules that follow, and [the approvals guide](/other-content/human-in-the-loop-approvals-for-ai-agents) covers Python’s `HumanInTheLoopMiddleware`.

## Resumable stream and reconnect on the LangGraph Agent Server

**A client that drops can rejoin a run and get the events it missed, as long as you create the run with `stream_resumable=True`.** That flag makes the server keep the stream’s chunks, and the client rejoins at `/threads/{thread_id}/runs/{run_id}/stream` with a `Last-Event-ID` header. Without it, `join_stream` still attaches, but the docs say “output is not buffered,” so the client misses what came before the join.

A thread stream follows every run on a thread over one connection, and it resumes the same way, as LangChain’s streaming docs show:

```
async for chunk in client.threads.join_stream(
    thread_id,
    last_event_id="<LAST_EVENT_ID>",
):
    print(chunk)
```

Pass `"-"` as the ID instead, and the thread’s stream replays from the beginning.

Any API server can serve any run’s stream, because queue workers publish their events over Redis pub/sub. The buffered chunks sit in Redis too, and since a long `RESUMABLE_STREAM_TTL_SECONDS` “can result in substantial Redis memory usage,” the docs say to keep it short and leave durability to checkpoints. And `on_disconnect` decides what a dropped client does to the run: the default `continue` lets it finish, and `cancel` stops it.

The browser needs the server too: join and rejoin with `useStream` “requires the LangGraph Agent Server.”

## LangGraph Agent Server self-hosted: queue workers and scaling

An Agent Server is two pools of containers built from one image: API servers that take requests and stream results, and queue workers that run your graph and write checkpoints. [Self-hosting AI agent infrastructure](/other-content/self-hosting-ai-agent-infrastructure) covers what Postgres and Redis each hold.

Self-hosted, the API server runs the queue itself until you set `queue.enabled: true`, which splits the two tiers so each scales on its own. Each queue worker runs up to `N_JOBS_PER_WORKER` runs at once (10 by default), and LangChain sizes the pool with this formula:

```
number_of_queue_workers = throughput_per_second * average_run_execution_time_seconds / N_JOBS_PER_WORKER
```

So 2 new runs a second that take 30 seconds each need 6 workers. **Autoscaling stays off until you configure it, so when every run slot is busy, new runs wait in the queue.** Each replica also opens up to `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` Postgres connections, so 10 replicas at 150 can open 1,500.

On Cloud you tune none of this, and a Serverless deployment runs one replica that handles 10 runs at once by default. Dedicated scales queue workers on CPU or backlog at 7 runs per worker. Redis and the database don’t autoscale, and a replica’s CPU and memory come from the deployment’s size, so LangChain’s fix for steady CPU pressure is a larger size.

## What does Cadenya offer that LangGraph and LangSmith Deployment don’t?

LangGraph and LangSmith Deployment make a graph durable, and you still write it, deploy it, and pay for the servers that hold its state. **Cadenya runs the agent loop itself, with durable state, approvals, and resumable event streams on its side, so your app starts an objective with one API call.** It fits next to LangGraph for your next agent, or in place of it. Here’s what that covers:

1.  **Nothing else to run.** There’s no checkpointer database, no Agent Server, no Redis, and no queue worker to size. The loop runs on Cadenya, so your deploys and restarts never touch a running objective.
2.  **No server license to check.** The Agent Server ships as `langgraph-api`, which PyPI lists under Elastic-2.0, and self-hosting it takes an Enterprise plan and a license key. Cadenya’s SDKs are Apache-2.0, and there’s no server to license.
3.  **Edits don’t break waiting runs.** An objective “keeps that variation’s configuration snapshot even if you edit the variation later,” so an edit to the variation never reaches an objective that’s halfway through.
4.  **SDKs for the versions you run today.** The TypeScript, Python, Ruby, and Go SDKs are all at 1.9.0 under Apache-2.0, and the TypeScript SDK has shipped 113 versions since April 2026. The Python SDK runs on Python 3.9, where `langgraph` asks for 3.10 and the Agent Server for 3.11.
5.  **A price in one line.** It’s free for 1,000 loops a month with no card, then $49 a month for 50,000 loops on Growth, and $0.0015 a loop after that. A loop is one LLM request made during an objective, so the bill has no seats, no deployment sizes, and no database hours.
6.  **Messages that wait their turn.** When a user writes while the loop is busy, a Continue call with `enqueue` set queues the message, and the agent picks it up before its next assistant turn.
7.  **Streams that resume from a durable log.** Every objective “carries a durable event log of its agent loop,” and its event stream takes a durable `objevt_` event ID as its `Last-Event-ID` reconnect cursor.
8.  **Approvals as configuration.** Require approval on a tool set for every call or for matching tools, and Cadenya “parks the Agent loop until it receives approval or a denial with optional steering.” Several calls can wait at once, each with its own `toolcall_` ID.
9.  **Compaction that runs on its own.** Compaction “runs automatically as context fills,” at 75% of the model’s context limit by default, with summarization, older-result clearing, or both set on the variation.
10.  **Your API as the tools, on the model you pick.** A tool set reads every operation from an OpenAPI document, and MCP servers and HTTP endpoints work too. The model is a setting on a variation, chosen from the AI providers in your workspace.

[How objectives work](/docs/guides/the-basics/objectives) walks through events, approvals, and Continue, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with `cadenya workspaces create --temporary`, run its first objectives there, and hand you a link to claim it, as [auth.md](https://cadenya.com/auth.md) explains. To create an account, sign up at [app.cadenya.com/signup](https://app.cadenya.com/signup?utm_source=cadenya.com&utm_medium=article&utm_campaign=langgraph-in-production), then copy your API key from the API keys page at `app.cadenya.com/account/apiKeys`.